static void search(Dict* args, void* vctx, String* txid, struct Allocator* reqAlloc)
{
    struct Context* ctx = Identity_check((struct Context*) vctx);
    String* addrStr = Dict_getStringC(args, "ipv6");

    int maxRequests = -1;
    uint64_t* maxRequestsPtr = Dict_getIntC(args, "maxRequests");
    if (maxRequestsPtr) { maxRequests = *maxRequestsPtr; }

    uint8_t addr[16];
    if (AddrTools_parseIp(addr, (uint8_t*) addrStr->bytes)) {
        Dict* resp = Dict_new(reqAlloc);
        Dict_putStringCC(resp, "error", "ipv6 invalid", reqAlloc);
        Admin_sendMessage(resp, txid, ctx->admin);
    } else {
        struct Allocator* alloc = Allocator_child(ctx->allocator);
        struct Search* s = Allocator_calloc(alloc, sizeof(struct Search), 1);
        s->promise = SearchRunner_search(addr, maxRequests, maxRequests, ctx->runner, alloc);
        s->ctx = ctx;
        s->txid = String_clone(txid, alloc);
        s->alloc = alloc;
        Identity_set(s);

        if (!s->promise) {
            Dict* resp = Dict_new(reqAlloc);
            Dict_putStringCC(resp, "error", "creating search", reqAlloc);
            Admin_sendMessage(resp, txid, ctx->admin);
            Allocator_free(alloc);
            return;
        }

        s->promise->userData = s;
        s->promise->callback = searchResponse;
    }
}
Exemple #2
0
List* CryptoAuth_getUsers(struct CryptoAuth* context, struct Allocator* alloc)
{
    struct CryptoAuth_pvt* ca = Identity_check((struct CryptoAuth_pvt*) context);

    List* users = List_new(alloc);
    for (struct CryptoAuth_User* u = ca->users; u; u = u->next) {
        List_addString(users, String_clone(u->login, alloc), alloc);
    }

    return users;
}
Exemple #3
0
static void subscribe(Dict* args, void* vcontext, String* txid)
{
    struct AdminLog* log = (struct AdminLog*) vcontext;
    String* levelName = Dict_getString(args, String_CONST("level"));
    enum Log_Level level = (levelName) ? Log_levelForName(levelName->bytes) : Log_Level_DEBUG;
    int64_t* lineNumPtr = Dict_getInt(args, String_CONST("line"));
    String* fileStr = Dict_getString(args, String_CONST("file"));
    const char* file = (fileStr && fileStr->len > 0) ? fileStr->bytes : NULL;
    char* error = "2+2=5";
    if (level == Log_Level_INVALID) {
        level = Log_Level_KEYS;
    }
    if (lineNumPtr && *lineNumPtr < 0) {
        error = "Invalid line number, must be positive or 0 to signify any line is acceptable.";
    } else if (log->subscriptionCount >= MAX_SUBSCRIPTIONS) {
        error = "Max subscription count reached.";
    } else {
        struct Subscription* sub = &log->subscriptions[log->subscriptionCount];
        sub->level = level;
        sub->alloc = Allocator_child(log->alloc);
        if (file) {
            int i;
            for (i = 0; i < FILE_NAME_COUNT; i++) {
                if (log->fileNames[i] && !strcmp(log->fileNames[i], file)) {
                    file = log->fileNames[i];
                    sub->internalName = true;
                    break;
                }
            }
            if (i == FILE_NAME_COUNT) {
                file = String_new(file, sub->alloc)->bytes;
                sub->internalName = false;
            }
        }
        sub->file = file;
        sub->lineNum = (lineNumPtr) ? *lineNumPtr : 0;
        sub->txid = String_clone(txid, sub->alloc);
        Random_bytes(log->rand, (uint8_t*) sub->streamId, 8);
        uint8_t streamIdHex[20];
        Hex_encode(streamIdHex, 20, sub->streamId, 8);
        Dict response = Dict_CONST(
            String_CONST("error"), String_OBJ(String_CONST("none")), Dict_CONST(
            String_CONST("streamId"), String_OBJ(String_CONST((char*)streamIdHex)), NULL
        ));
        Admin_sendMessage(&response, txid, log->admin);
        log->subscriptionCount++;
        return;
    }

    Dict response = Dict_CONST(
        String_CONST("error"), String_OBJ(String_CONST(error)), NULL
    );
    Admin_sendMessage(&response, txid, log->admin);
}
Exemple #4
0
void CryptoAuth_setAuth(const String* password,
                        const String* login,
                        struct CryptoAuth_Session* caSession)
{
    struct CryptoAuth_Session_pvt* session =
        Identity_check((struct CryptoAuth_Session_pvt*)caSession);

    if (!password && (session->password || session->authType)) {
        session->password = NULL;
        session->authType = 0;
    } else if (!session->password || !String_equals(session->password, password)) {
        session->password = String_clone(password, session->alloc);
        session->authType = 1;
        if (login) {
            session->authType = 2;
            session->login = String_clone(login, session->alloc);
        }
    } else {
        return;
    }
    reset(session);
}
Exemple #5
0
List* CryptoAuth_getUsers(struct CryptoAuth* context, struct Allocator* alloc)
{
    struct CryptoAuth_pvt* ctx = Identity_check((struct CryptoAuth_pvt*) context);
    uint32_t count = ctx->passwordCount;

    List* users = NULL;

    for (uint32_t i = 0; i < count; i++ )
    {
        users = List_addString(users, String_clone(ctx->passwords[i].user, alloc), alloc);
    }

    return users;
}
Exemple #6
0
int CryptoAuth_addUser_ipv6(String* password,
                            String* login,
                            uint8_t ipv6[16],
                            struct CryptoAuth* cryptoAuth)
{
    struct CryptoAuth_pvt* ca = Identity_check((struct CryptoAuth_pvt*) cryptoAuth);

    struct Allocator* alloc = Allocator_child(ca->allocator);
    struct CryptoAuth_User* user = Allocator_calloc(alloc, sizeof(struct CryptoAuth_User), 1);
    user->alloc = alloc;
    Identity_set(user);

    if (!login) {
        int i = 0;
        for (struct CryptoAuth_User* u = ca->users; u; u = u->next) { i++; }
        user->login = login = String_printf(alloc, "Anon #%d", i);
    } else {
        user->login = String_clone(login, alloc);
    }

    union CryptoHeader_Challenge ac;
    // Users specified with a login field might want to use authType 1 still.
    hashPassword(user->secret, &ac, login, password, 2);
    Bits_memcpyConst(user->userNameHash, ac.bytes, CryptoHeader_Challenge_KEYSIZE);
    hashPassword(user->secret, &ac, NULL, password, 1);
    Bits_memcpyConst(user->passwordHash, ac.bytes, CryptoHeader_Challenge_KEYSIZE);

    for (struct CryptoAuth_User* u = ca->users; u; u = u->next) {
        if (Bits_memcmp(user->secret, u->secret, 32)) {
        } else if (!login) {
        } else if (String_equals(login, u->login)) {
            Allocator_free(alloc);
            return CryptoAuth_addUser_DUPLICATE;
        }
    }

    if (ipv6) {
        Bits_memcpyConst(user->restrictedToip6, ipv6, 16);
    }

    // Add the user to the *end* of the list
    for (struct CryptoAuth_User** up = &ca->users; ; up = &(*up)->next) {
        if (!*up) {
            *up = user;
            break;
        }
    }

    return 0;
}
Exemple #7
0
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);
}
Exemple #8
0
int InterfaceController_getPeerStats(struct InterfaceController* ifController,
                                     struct Allocator* alloc,
                                     struct InterfaceController_PeerStats** statsOut)
{
    struct InterfaceController_pvt* ic =
        Identity_check((struct InterfaceController_pvt*) ifController);

    int count = 0;
    for (int i = 0; i < ic->icis->length; i++) {
        struct InterfaceController_Iface_pvt* ici = ArrayList_OfIfaces_get(ic->icis, i);
        count += ici->peerMap.count;
    }

    struct InterfaceController_PeerStats* stats =
        Allocator_calloc(alloc, sizeof(struct InterfaceController_PeerStats), count);

    int xcount = 0;
    for (int j = 0; j < ic->icis->length; j++) {
        struct InterfaceController_Iface_pvt* ici = ArrayList_OfIfaces_get(ic->icis, j);
        for (int i = 0; i < (int)ici->peerMap.count; i++) {
            struct Peer* peer = Identity_check((struct Peer*) ici->peerMap.values[i]);
            struct InterfaceController_PeerStats* s = &stats[xcount];
            xcount++;
            Bits_memcpy(&s->addr, &peer->addr, sizeof(struct Address));
            s->bytesOut = peer->bytesOut;
            s->bytesIn = peer->bytesIn;
            s->timeOfLastMessage = peer->timeOfLastMessage;
            s->state = peer->state;
            s->isIncomingConnection = peer->isIncomingConnection;
            if (peer->caSession->displayName) {
                s->user = String_clone(peer->caSession->displayName, alloc);
            }
            struct ReplayProtector* rp = &peer->caSession->replayProtector;
            s->duplicates = rp->duplicates;
            s->lostPackets = rp->lostPackets;
            s->receivedOutOfRange = rp->receivedOutOfRange;

            struct PeerLink_Kbps kbps;
            PeerLink_kbps(peer->peerLink, &kbps);
            s->sendKbps = kbps.sendKbps;
            s->recvKbps = kbps.recvKbps;
        }
    }

    Assert_true(xcount == count);

    *statsOut = stats;
    return count;
}
Exemple #9
0
static String* getCorePath(struct Allocator* alloc)
{
    struct Allocator* alloc2 = Allocator_child(alloc);
    char* cjdroute2Path = Process_getPath(alloc2);
    char* lastSlash = strrchr(cjdroute2Path, '/');
    Assert_always(lastSlash != NULL);
    *lastSlash = '\0';
    String* tempOutput = String_printf(alloc2, "%s/cjdns", cjdroute2Path);
    String* output = NULL;
    if (fileExists(tempOutput->bytes)) {
        output = String_clone(tempOutput, alloc);
    }
    Allocator_free(alloc2);
    return output;
}
Exemple #10
0
struct InterfaceController_Iface* InterfaceController_newIface(struct InterfaceController* ifc,
                                                               String* name,
                                                               struct Allocator* alloc)
{
    struct InterfaceController_pvt* ic = Identity_check((struct InterfaceController_pvt*) ifc);

    struct InterfaceController_Iface_pvt* ici =
        Allocator_calloc(alloc, sizeof(struct InterfaceController_Iface_pvt), 1);
    ici->name = String_clone(name, alloc);
    ici->peerMap.allocator = alloc;
    ici->ic = ic;
    ici->alloc = alloc;
    ici->pub.addrIf.send = handleIncomingFromWire;
    ici->pub.ifNum = ArrayList_OfIfaces_add(ic->icis, ici);

    Identity_set(ici);

    return &ici->pub;
}
Exemple #11
0
int InterfaceController_bootstrapPeer(struct InterfaceController* ifc,
                                      int interfaceNumber,
                                      uint8_t* herPublicKey,
                                      const struct Sockaddr* lladdrParm,
                                      String* password,
                                      String* login,
                                      String* user,
                                      struct Allocator* alloc)
{
    struct InterfaceController_pvt* ic = Identity_check((struct InterfaceController_pvt*) ifc);

    Assert_true(herPublicKey);
    Assert_true(password);

    struct InterfaceController_Iface_pvt* ici = ArrayList_OfIfaces_get(ic->icis, interfaceNumber);

    if (!ici) {
        return InterfaceController_bootstrapPeer_BAD_IFNUM;
    }

    Log_debug(ic->logger, "bootstrapPeer total [%u]", ici->peerMap.count);

    uint8_t ip6[16];
    AddressCalc_addressForPublicKey(ip6, herPublicKey);
    if (!AddressCalc_validAddress(ip6) || !Bits_memcmp(ic->ca->publicKey, herPublicKey, 32)) {
        return InterfaceController_bootstrapPeer_BAD_KEY;
    }

    struct Allocator* epAlloc = Allocator_child(ici->alloc);

    struct Sockaddr* lladdr = Sockaddr_clone(lladdrParm, epAlloc);

    // TODO(cjd): eps are created in 3 places, there should be a factory function.
    struct Peer* ep = Allocator_calloc(epAlloc, sizeof(struct Peer), 1);
    int index = Map_EndpointsBySockaddr_put(&lladdr, &ep, &ici->peerMap);
    Assert_true(index >= 0);
    ep->alloc = epAlloc;
    ep->handle = ici->peerMap.handles[index];
    ep->lladdr = lladdr;
    ep->ici = ici;
    ep->isIncomingConnection = false;
    Bits_memcpy(ep->addr.key, herPublicKey, 32);
    Address_getPrefix(&ep->addr);
    Identity_set(ep);
    Allocator_onFree(epAlloc, closeInterface, ep);
    Allocator_onFree(alloc, freeAlloc, epAlloc);

    ep->peerLink = PeerLink_new(ic->eventBase, epAlloc);
    ep->caSession = CryptoAuth_newSession(ic->ca, epAlloc, herPublicKey, false, "outer");
    CryptoAuth_setAuth(password, login, ep->caSession);
    if (user) {
        ep->caSession->displayName = String_clone(user, epAlloc);
    }

    ep->switchIf.send = sendFromSwitch;

    if (SwitchCore_addInterface(ic->switchCore, &ep->switchIf, epAlloc, &ep->addr.path)) {
        Log_debug(ic->logger, "bootstrapPeer() SwitchCore out of space");
        Allocator_free(epAlloc);
        return InterfaceController_bootstrapPeer_OUT_OF_SPACE;
    }

    // We want the node to immedietly be pinged but we don't want it to appear unresponsive because
    // the pinger will only ping every (PING_INTERVAL * 8) so we set timeOfLastMessage to
    // (now - pingAfterMilliseconds - 1) so it will be considered a "lazy node".
    ep->timeOfLastMessage =
        Time_currentTimeMilliseconds(ic->eventBase) - ic->pingAfterMilliseconds - 1;

    if (Defined(Log_INFO)) {
        struct Allocator* tempAlloc = Allocator_child(alloc);
        String* addrStr = Address_toString(&ep->addr, tempAlloc);
        Log_info(ic->logger, "Adding peer [%s] from bootstrapPeer()", addrStr->bytes);
        Allocator_free(tempAlloc);
    }

    // We can't just add the node directly to the routing table because we do not know
    // the version. We'll send it a switch ping and when it responds, we will know it's
    // key (if we don't already) and version number.
    sendPing(ep);

    return 0;
}
Exemple #12
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
    }));
Exemple #13
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
    });
}
Exemple #14
0
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 udpInterface(Dict* config, struct Context* ctx)
{
    List* ifaces = Dict_getList(config, String_CONST("UDPInterface"));
    if (!ifaces) {
        ifaces = 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);
        }
        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;
            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* value = entry->val->as.dictionary;
                Log_keys(ctx->logger, "Attempting to connect to node [%s].", key->bytes);
                key = String_clone(key, perCallAlloc);
                char* lastColon = 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;
                    }
                }
                Dict_putString(value, String_CONST("address"), key, perCallAlloc);
                rpcCall(String_CONST("UDPInterface_beginConnection"), value, ctx, perCallAlloc);
                entry = entry->next;
            }
            Allocator_free(perCallAlloc);
        }
    }
}
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);
Exemple #17
0
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* value = entry->val->as.dictionary;
                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.
                    Log_critical(ctx->logger, "Couldn't add connection [%s], "
                                 "hostnames aren't supported.", key->bytes);
                    exit(-1);
                }
                Dict_putInt(value, String_CONST("interfaceNumber"), ifNum, perCallAlloc);
                Dict_putString(value, String_CONST("address"), key, perCallAlloc);
                rpcCall(String_CONST("UDPInterface_beginConnection"), value, ctx, perCallAlloc);

                // Make a IPTunnel exception for this node
                Dict* aed = Dict_new(perCallAlloc);
                *lastColon = '\0';
                Dict_putString(aed, String_CONST("route"), String_new(key->bytes, perCallAlloc),
                               perCallAlloc);
                *lastColon = ':';
                rpcCall(String_CONST("RouteGen_addException"), aed, ctx, perCallAlloc);

                entry = entry->next;
            }
            Allocator_free(perCallAlloc);
        }
    }
}
Exemple #18
0
void GlobalConfig_setTunName(struct GlobalConfig* conf, String* name)
{
    struct GlobalConfig_pvt* ctx = Identity_check((struct GlobalConfig_pvt*) conf);
    // This is a memory leak but hopefully this function doesn't get called too much...
    ctx->tunName = String_clone(name, ctx->alloc);
}