Exemple #1
0
static uint8_t sendMessage(struct Message* message, struct Interface* ethIf)
{
    struct ETHInterface* context = Identity_cast((struct ETHInterface*) ethIf);

    struct sockaddr_ll addr;
    Bits_memcpyConst(&addr, &context->addrBase, sizeof(struct sockaddr_ll));
    Message_pop(message, addr.sll_addr, 8);

    /* Cut down on the noise
    uint8_t buff[sizeof(addr) * 2 + 1] = {0};
    Hex_encode(buff, sizeof(buff), (uint8_t*)&addr, sizeof(addr));
    Log_debug(context->logger, "Sending ethernet frame to [%s]", buff);
    */

    // Check if we will have to pad the message and pad if necessary.
    int pad = 0;
    for (int length = message->length; length+2 < MIN_PACKET_SIZE; length += 8) {
        pad++;
    }
    if (pad > 0) {
        int length = message->length;
        Message_shift(message, pad*8);
        Bits_memset(message->bytes, 0, pad*8);
        Bits_memmove(message->bytes, &message->bytes[pad*8], length);
    }
    Assert_true(pad < 8);
    uint16_t padAndId_be = Endian_hostToBigEndian16((context->id << 3) | pad);
    Message_push(message, &padAndId_be, 2);

    if (sendto(context->socket,
               message->bytes,
               message->length,
               0,
               (struct sockaddr*) &addr,
               sizeof(struct sockaddr_ll)) < 0)
    {
        switch (errno) {
            case EMSGSIZE:
                return Error_OVERSIZE_MESSAGE;

            case ENOBUFS:
            case EAGAIN:
                return Error_LINK_LIMIT_EXCEEDED;

            default:;
                Log_info(context->logger, "Got error sending to socket [%s]", strerror(errno));
        }
    }
    return 0;
}
static int closeInterface(struct Allocator_OnFreeJob* job)
{
    struct IFCPeer* toClose = Identity_cast((struct IFCPeer*) job->userData);

    struct Context* ic = ifcontrollerForPeer(toClose);

    // flush the peer from the table...
    RouterModule_brokenPath(toClose->switchLabel, ic->routerModule);

    int index = Map_OfIFCPeerByExernalIf_indexForHandle(toClose->handle, &ic->peerMap);
    Assert_true(index >= 0);
    Map_OfIFCPeerByExernalIf_remove(index, &ic->peerMap);
    return 0;
}
Exemple #3
0
static struct Address* getWorst(struct RumorMill_pvt* rm)
{
    struct Address* worst = NULL;
    int howBadIsTheWorst = 0;
    for (int i = 0; i < rm->pub.count; i++) {
        int howBad = getBadness(&rm->pub.addresses[i], rm->selfAddr);
        if (howBad > howBadIsTheWorst) {
            howBadIsTheWorst = howBad;
            worst = &rm->pub.addresses[i];
        }
    }
    Assert_true(worst);
    return worst;
}
Exemple #4
0
static void disconnectAdopted(struct Allocator_pvt* parent, struct Allocator_pvt* child)
{
    Assert_true(parent->adoptions);
    Assert_true(parent->adoptions->children);
    Assert_true(child->adoptions);
    Assert_true(child->adoptions->parents);
    Assert_true(disconnectAllocator(child, &parent->adoptions->children));
    Assert_true(disconnectAllocator(parent, &child->adoptions->parents));
}
Exemple #5
0
void AddrTools_printShortIp(uint8_t output[40], const uint8_t binIp[16])
{
    /* The chances of hitting :0:0: and breaking
     * RFC5952 are 1 in (1 / (2^16))^2 * 6.
     * E. Siler
     */

    char *p = output;
    int i = 0;
    for (; i < 16;) {
        if ((size_t)p != (size_t)output) {
            *p++= ':';
        }

        if (binIp[i] > 0x0F) {
            Hex_encode(p, 2, &binIp[i++], 1);
            p += 2;
        } else if (binIp[i] > 0x00) {
            *p++ = Hex_encodeLowNibble(binIp[i++]);
        } else {
            ++i;
            if (binIp[i] > 0x0F) {
                Hex_encode(p, 2, &binIp[i++], 1);
                p += 2;
            } else {
                *p++ = Hex_encodeLowNibble(binIp[i++]);
            }
            continue;
        }
        Hex_encode(p, 2, &binIp[i++], 1);
        p += 2;
    }
    *p = '\0';

    Assert_true((size_t)p <= ((size_t)output + 40));
    Assert_true(i <= 16);
}
Exemple #6
0
static Iface_DEFUN handleIncomingFromWire(struct Message* msg, struct Iface* addrIf)
{
    struct InterfaceController_Iface_pvt* ici =
        Identity_containerOf(addrIf, struct InterfaceController_Iface_pvt, pub.addrIf);

    struct Sockaddr* lladdr = (struct Sockaddr*) msg->bytes;
    if (msg->length < Sockaddr_OVERHEAD || msg->length < lladdr->addrLen) {
        Log_debug(ici->ic->logger, "DROP runt");
        return NULL;
    }

    Assert_true(!((uintptr_t)msg->bytes % 4) && "alignment fault");
    Assert_true(!((uintptr_t)lladdr->addrLen % 4) && "alignment fault");

    // noisy
    if (Defined(Log_DEBUG) && false) {
        char* printedAddr = Hex_print(&lladdr[1], lladdr->addrLen - Sockaddr_OVERHEAD, msg->alloc);
        Log_debug(ici->ic->logger, "Incoming message from [%s]", printedAddr);
    }

    if (lladdr->flags & Sockaddr_flags_BCAST) {
        return handleBeacon(msg, ici);
    }

    int epIndex = Map_EndpointsBySockaddr_indexForKey(&lladdr, &ici->peerMap);
    if (epIndex == -1) {
        return handleUnexpectedIncoming(msg, ici);
    }

    struct Peer* ep = Identity_check((struct Peer*) ici->peerMap.values[epIndex]);
    Message_shift(msg, -lladdr->addrLen, NULL);
    if (CryptoAuth_decrypt(ep->caSession, msg)) {
        return NULL;
    }
    PeerLink_recv(msg, ep->peerLink);
    return receivedPostCryptoAuth(msg, ep, ici->ic);
}
Exemple #7
0
static void sessionStats(Dict* args,
                         void* vcontext,
                         String* txid,
                         struct Allocator* alloc)
{
    struct Context* context = vcontext;
    int64_t* handleP = Dict_getInt(args, String_CONST("handle"));
    uint32_t handle = *handleP;

    struct SessionManager_Session* session = SessionManager_sessionForHandle(handle, context->sm);
    uint8_t* ip6 = SessionManager_getIp6(handle, context->sm);

    Dict* r = Dict_new(alloc);
    if (!session) {
        Dict_putString(r, String_CONST("error"), String_CONST("no such session"), alloc);
        Admin_sendMessage(r, txid, context->admin);
        return;
    }
    // both or neither
    Assert_true(ip6);

    uint8_t printedAddr[40];
    AddrTools_printIp(printedAddr, ip6);
    Dict_putString(r, String_CONST("ip6"), String_new(printedAddr, alloc), alloc);

    Dict_putString(r,
                   String_CONST("state"),
                   String_new(CryptoAuth_stateString(session->cryptoAuthState), alloc),
                   alloc);

    struct ReplayProtector* rp = CryptoAuth_getReplayProtector(session->internal);
    Dict_putInt(r, String_CONST("duplicates"), rp->duplicates, alloc);
    Dict_putInt(r, String_CONST("lostPackets"), rp->lostPackets, alloc);
    Dict_putInt(r, String_CONST("receivedOutOfRange"), rp->receivedOutOfRange, alloc);

    uint8_t* key = CryptoAuth_getHerPublicKey(session->internal);
    Dict_putString(r, String_CONST("publicKey"), Key_stringify(key, alloc), alloc);
    Dict_putInt(r, String_CONST("version"), session->version, alloc);
    Dict_putInt(r, String_CONST("handle"),
                Endian_bigEndianToHost32(session->receiveHandle_be), alloc);
    Dict_putInt(r, String_CONST("sendHandle"),
                Endian_bigEndianToHost32(session->sendHandle_be), alloc);

    Dict_putInt(r, String_CONST("timeOfLastIn"), session->timeOfLastIn, alloc);
    Dict_putInt(r, String_CONST("timeOfLastOut"), session->timeOfLastOut, alloc);

    Admin_sendMessage(r, txid, context->admin);
    return;
}
Exemple #8
0
static int rpcCall0(String* function,
                    Dict* args,
                    struct Context* ctx,
                    struct Allocator* alloc,
                    Dict** resultP,
                    bool exitIfError)
{
    ctx->currentReqAlloc = Allocator_child(alloc);
    ctx->currentResult = NULL;
    struct AdminClient_Promise* promise = AdminClient_rpcCall(function, args, ctx->client, alloc);
    promise->callback = rpcCallback;
    promise->userData = ctx;

    EventBase_beginLoop(ctx->base);

    struct AdminClient_Result* res = ctx->currentResult;
    Assert_true(res);

    if (res->err) {
        Log_critical(ctx->logger,
                      "Failed to make function call [%s], error: [%s]",
                      AdminClient_errorString(res->err),
                      function->bytes);
        die(res, ctx, alloc);
    }
    String* error = Dict_getString(res->responseDict, String_CONST("error"));
    int ret = 0;
    if (error && !String_equals(error, String_CONST("none"))) {
        if (exitIfError) {
            Log_critical(ctx->logger,
                         "Got error [%s] calling [%s]",
                         error->bytes,
                         function->bytes);
            die(res, ctx, alloc);
        }
        Log_warn(ctx->logger, "Got error [%s] calling [%s], ignoring.",
                 error->bytes, function->bytes);
        ret = 1;
    }

    if (resultP) {
        *resultP = res->responseDict;
    } else {
        Allocator_free(ctx->currentReqAlloc);
    }
    ctx->currentReqAlloc = NULL;

    return ret;
}
Exemple #9
0
static void traceStep(struct RouteTracer_Trace* trace, struct Node* next)
{
    struct RouteTracer_pvt* ctx = Identity_cast((struct RouteTracer_pvt*)trace->tracer);

    if (!next) {
        // can't find a next node, stalled.
        Timeout_setTimeout(noPeers, trace, 0, trace->tracer->eventBase, trace->pub.alloc);
        return;
    }

    Assert_true(LabelSplicer_routesThrough(trace->target, next->address.path));

    trace->lastNodeAsked = next->address.path;

    struct RouterModule_Promise* rp =
        RouterModule_newMessage(next, 0, ctx->router, trace->pub.alloc);

    Dict* message = Dict_new(rp->alloc);

    #ifdef Version_4_COMPAT
        if (next->version < 5) {
            // The node doesn't support the new API so try running a search for
            // the bitwise complement of their address to get some peers.
            Dict_putString(message, CJDHTConstants_QUERY, CJDHTConstants_QUERY_FN, rp->alloc);
            String* notAddr = String_newBinary((char*)next->address.ip6.bytes, 16, rp->alloc);
            for (int i = 0; i < 16; i++) {
                notAddr->bytes[i] ^= 0xff;
            }
            Dict_putString(message, CJDHTConstants_TARGET, notAddr, rp->alloc);
            log(ctx->logger, trace, "Sending legacy search method because getpeers is unavailable");
        } else {
    #endif

    Dict_putString(message, CJDHTConstants_QUERY, CJDHTConstants_QUERY_GP, rp->alloc);
    uint64_t labelForThem = LabelSplicer_unsplice(trace->target, next->address.path);
    labelForThem = Endian_hostToBigEndian64(labelForThem);
    String* target = String_newBinary((char*)&labelForThem, 8, rp->alloc);
    Dict_putString(message, CJDHTConstants_TARGET, target, rp->alloc);
    log(ctx->logger, trace, "Sending getpeers request");

    #ifdef Version_4_COMPAT
        }
    #endif

    rp->userData = trace;
    rp->callback = responseCallback;

    RouterModule_sendMessage(rp, message);
}
Exemple #10
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;
}
// Incoming message which has passed through the cryptoauth and needs to be forwarded to the switch.
static uint8_t receivedAfterCryptoAuth(struct Message* msg, struct Interface* cryptoAuthIf)
{
    struct InterfaceController_Peer* ep =
        Identity_check((struct InterfaceController_Peer*) cryptoAuthIf->receiverContext);
    struct InterfaceController_pvt* ic = ifcontrollerForPeer(ep);

    ep->bytesIn += msg->length;

    int caState = CryptoAuth_getState(cryptoAuthIf);
    if (ep->state < InterfaceController_PeerState_ESTABLISHED) {
        // EP states track CryptoAuth states...
        ep->state = caState;
        if (caState == CryptoAuth_ESTABLISHED) {
            moveEndpointIfNeeded(ep, ic);
        } else {
            // prevent some kinds of nasty things which could be done with packet replay.
            // This is checking the message switch header and will drop it unless the label
            // directs it to *this* router.
            if (msg->length < 8 || msg->bytes[7] != 1) {
                Log_info(ic->logger, "DROP message because CA is not established.");
                return Error_NONE;
            } else {
                // When a "server" gets a new connection from a "client" the router doesn't
                // know about that client so if the client sends a packet to the server, the
                // server will be unable to handle it until the client has sent inter-router
                // communication to the server. Here we will ping the client so when the
                // server gets the ping response, it will insert the client into its table
                // and know its version.

                // prevent DoS by limiting the number of times this can be called per second
                // limit it to 7, this will affect innocent packets but it doesn't matter much
                // since this is mostly just an optimization and for keeping the tests happy.
                if ((ep->pingCount + 1) % 7) {
                    sendPing(ep);
                }
            }
        }
    } else if (ep->state == InterfaceController_PeerState_UNRESPONSIVE
        && caState == CryptoAuth_ESTABLISHED)
    {
        ep->state = InterfaceController_PeerState_ESTABLISHED;
    } else {
        ep->timeOfLastMessage = Time_currentTimeMilliseconds(ic->eventBase);
    }

    Identity_check(ep);
    Assert_true(!(msg->capacity % 4));
    return Interface_receiveMessage(&ep->switchIf, msg);
}
static int closeInterface(struct Allocator_OnFreeJob* job)
{
    struct InterfaceController_Peer* toClose =
        Identity_check((struct InterfaceController_Peer*) job->userData);

    struct InterfaceController_pvt* ic = ifcontrollerForPeer(toClose);

    // flush the peer from the table...
    Router_disconnectedPeer(ic->router, toClose->switchLabel);

    int index = Map_OfIFCPeerByExernalIf_indexForHandle(toClose->handle, &ic->peerMap);
    Assert_true(index >= 0);
    Map_OfIFCPeerByExernalIf_remove(index, &ic->peerMap);
    return 0;
}
Exemple #13
0
static struct Ducttape_MessageHeader* getDtHeader(struct Message* message, bool init)
{
    int padding = message->padding;
    Assert_true(padding > Ducttape_MessageHeader_SIZE);
    Message_shift(message, padding);
    struct Ducttape_MessageHeader* dtHeader = (struct Ducttape_MessageHeader*) message->bytes;
    Message_shift(message, -padding);
    if (init) {
        Bits_memset(dtHeader, 0, Ducttape_MessageHeader_SIZE);
        Identity_set(dtHeader);
    } else {
        Identity_check(dtHeader);
    }
    return dtHeader;
}
Exemple #14
0
void NetPlatform_addAddress(const char* interfaceName,
                            const uint8_t* address,
                            int prefixLen,
                            int addrFam,
                            struct Log* logger,
                            struct Except* eh)
{
    if (addrFam == Sockaddr_AF_INET6) {
        addIp6Address(interfaceName, address, prefixLen, logger, eh);
    } else if (addrFam == Sockaddr_AF_INET) {
        addIp4Address(interfaceName, address, prefixLen, logger, eh);
    } else {
        Assert_true(0);
    }
}
Exemple #15
0
static Iface_DEFUN messageToAngel(struct Message* msg, struct Iface* iface)
{
    struct NodeContext* ctx = Identity_check((struct NodeContext*) iface);
    if (ctx->boundAddr) { return 0; }
    struct Allocator* alloc = Allocator_child(ctx->alloc);
    Dict* config = BencMessageReader_read(msg, alloc, NULL);
    Dict* admin = Dict_getDict(config, String_CONST("admin"));
    String* bind = Dict_getString(admin, String_CONST("bind"));
    struct Sockaddr_storage ss;
    Assert_true(!Sockaddr_parse(bind->bytes, &ss));
    ctx->boundAddr = Sockaddr_clone(&ss.addr, ctx->alloc);
    Allocator_free(alloc);
    EventBase_endLoop(ctx->base);
    return 0;
}
Exemple #16
0
static void onConnectionParent(struct Pipe* p, int status)
{
    Assert_true(!status);
    struct Context* c = Identity_check((struct Context*) p->userData);

    struct Allocator* alloc = Allocator_child(c->alloc);
    uint8_t* bytes = Allocator_calloc(alloc, CString_strlen(MESSAGE) + 1, 1);
    Bits_memcpy(bytes, MESSAGE, CString_strlen(MESSAGE));
    struct Message* m = Allocator_clone(alloc, (&(struct Message) {
        .length = CString_strlen(MESSAGE),
        .padding = 0,
        .capacity = CString_strlen(MESSAGE),
        .alloc = alloc,
        .bytes = bytes
    }));
Exemple #17
0
static uint8_t sendTo(struct Message* msg, struct Interface* iface)
{
    struct TestFramework_Link* link =
        Identity_check((struct TestFramework_Link*)iface->senderContext);

    Assert_true(!((uintptr_t)msg->bytes % 4) || !"alignment fault");
    Assert_true(!(msg->capacity % 4) || !"length fault");
    Assert_true(((int)msg->capacity >= msg->length) || !"length fault0");

    struct Interface* dest;
    struct TestFramework* srcTf;
    if (&link->destIf == iface) {
        dest = &link->srcIf;
        srcTf = link->dest;
    } else if (&link->srcIf == iface) {
        dest = &link->destIf;
        srcTf = link->src;
    } else {
        Assert_true(false);
    }

    printf("Transferring message to [%p] - message length [%d]\n", (void*)dest, msg->length);

    // Store the original message and a copy of the original so they can be compared later.
    srcTf->lastMsgBackup = Message_clone(msg, srcTf->alloc);
    srcTf->lastMsg = msg;
    if (msg->alloc) {
        // If it's a message which was buffered inside of CryptoAuth then it will be freed
        // so by adopting the allocator we can hold it in memory.
        Allocator_adopt(srcTf->alloc, msg->alloc);
    }

    // Copy the original and send that to the other end.
    struct Message* sendMsg = Message_clone(msg, dest->allocator);
    return dest->receiveMessage(sendMsg, dest);
}
Exemple #18
0
static uint8_t sendMessage(struct Message* message, struct Interface* interface)
{
    struct CryptoAuth_Wrapper* wrapper =
        Identity_cast((struct CryptoAuth_Wrapper*) interface->senderContext);

    // If there has been no incoming traffic for a while, reset the connection to state 0.
    // This will prevent "connection in bad state" situations from lasting forever.
    uint64_t nowSecs = Time_currentTimeSeconds(wrapper->context->eventBase);

    if (nowSecs - wrapper->timeOfLastPacket > wrapper->context->pub.resetAfterInactivitySeconds) {
        Log_debug(wrapper->context->logger, "No traffic in [%d] seconds, resetting connection.",
                  (int) (nowSecs - wrapper->timeOfLastPacket));

        wrapper->timeOfLastPacket = nowSecs;
        CryptoAuth_reset(interface);
        return encryptHandshake(message, wrapper);
    }

    #ifdef Log_DEBUG
        Assert_true(!((uintptr_t)message->bytes % 4) || !"alignment fault");
    #endif

    // nextNonce 0: sending hello, we are initiating connection.
    // nextNonce 1: sending another hello, nothing received yet.
    // nextNonce 2: sending key, hello received.
    // nextNonce 3: sending key again, no data packet recieved yet.
    // nextNonce >3: handshake complete
    //
    // if it's a blind handshake, every message will be empty and nextNonce will remain
    // zero until the first message is received back.
    if (wrapper->nextNonce < 5) {
        if (wrapper->nextNonce < 4) {
            return encryptHandshake(message, wrapper);
        } else {
            Log_debug(wrapper->context->logger,
                       "@%p Doing final step to send message. nonce=4\n", (void*) wrapper);
            uint8_t secret[32];
            getSharedSecret(secret,
                            wrapper->secret,
                            wrapper->tempKey,
                            NULL,
                            wrapper->context->logger);
            Bits_memcpyConst(wrapper->secret, secret, 32);
        }
    }

    return encryptMessage(message, wrapper);
}
Exemple #19
0
struct AddrInterface* TUNTools_setupUDP(struct EventBase* base,
                                        struct Sockaddr* bindAddr,
                                        struct Allocator* allocator,
                                        struct Log* logger)
{
    // Mac OSX and BSD do not set up their TUN devices synchronously.
    // We'll just keep on trying until this works.
    struct AddrInterface* udp = NULL;
    for (int i = 0; i < 20; i++) {
        if ((udp = setupUDP2(base, bindAddr, allocator, logger))) {
            break;
        }
    }
    Assert_true(udp);
    return udp;
}
Exemple #20
0
/**
 * Encrypt and authenticate.
 * Shifts the message by 16 bytes.
 *
 * @param nonce a 24 byte number, may be random, cannot repeat.
 * @param msg a message to encipher and authenticate.
 * @param secret a shared secret.
 */
static inline void encryptRndNonce(uint8_t nonce[24],
                                   struct Message* msg,
                                   uint8_t secret[32])
{
    Assert_true(msg->padding >= 32);
    uint8_t* startAt = msg->bytes - 32;
    // This function trashes 16 bytes of the padding so we will put it back
    uint8_t paddingSpace[16];
    Bits_memcpyConst(paddingSpace, startAt, 16);
    Bits_memset(startAt, 0, 32);
    crypto_box_curve25519xsalsa20poly1305_afternm(
        startAt, startAt, msg->length + 32, nonce, secret);

    Bits_memcpyConst(startAt, paddingSpace, 16);
    Message_shift(msg, 16, NULL);
}
Exemple #21
0
/**
 * Send a search request to the next node in this search.
 * This is called whenever a response comes in or after the global mean response time passes.
 */
static void searchStep(struct SearchRunner_Search* search)
{
    struct SearchRunner_pvt* ctx = Identity_check((struct SearchRunner_pvt*)search->runner);

    struct Node_Two* node;
    struct SearchStore_Node* nextSearchNode;
    for (;;) {
        nextSearchNode = SearchStore_getNextNode(search->search);

        // If the number of requests sent has exceeded the max search requests, let's stop there.
        if (search->totalRequests >= MAX_REQUESTS_PER_SEARCH || nextSearchNode == NULL) {
            if (search->pub.callback) {
                search->pub.callback(&search->pub, 0, NULL, NULL);
            }
            Allocator_free(search->pub.alloc);
            return;
        }

        node = NodeStore_getBest(&nextSearchNode->address, ctx->nodeStore);

        if (!node) { continue; }
        if (node == ctx->nodeStore->selfNode) { continue; }
        if (Bits_memcmp(node->address.ip6.bytes, nextSearchNode->address.ip6.bytes, 16)) {
            continue;
        }

        break;
    }

    Assert_true(node != ctx->nodeStore->selfNode);

    Bits_memcpyConst(&search->lastNodeAsked, &node->address, sizeof(struct Address));

    struct RouterModule_Promise* rp =
        RouterModule_newMessage(&node->address, 0, ctx->router, search->pub.alloc);

    Dict* message = Dict_new(rp->alloc);
    Dict_putString(message, CJDHTConstants_QUERY, CJDHTConstants_QUERY_FN, rp->alloc);
    Dict_putString(message, CJDHTConstants_TARGET, search->targetStr, rp->alloc);

    rp->userData = search;
    rp->callback = searchCallback;

    RouterModule_sendMessage(rp, message);

    search->totalRequests++;
}
Exemple #22
0
/**
 * Handle an incoming control message from a switch.
 *
 * @param context the ducttape context.
 * @param message the control message, this should be alligned on the beginning of the content,
 *                that is to say, after the end of the switch header.
 * @param switchHeader the header.
 * @param switchIf the interface which leads to the switch.
 * @param isFormV8 true if the control message is in the form specified by protocol version 8+
 */
static Iface_DEFUN incomingFromCore(struct Message* msg, struct Iface* coreIf)
{
    struct ControlHandler_pvt* ch = Identity_check((struct ControlHandler_pvt*) coreIf);

    struct RouteHeader routeHdr;
    Message_pop(msg, &routeHdr, RouteHeader_SIZE, NULL);
    uint8_t labelStr[20];
    uint64_t label = Endian_bigEndianToHost64(routeHdr.sh.label_be);
    AddrTools_printPath(labelStr, label);
    // happens in benchmark
    // Log_debug(ch->log, "ctrl packet from [%s]", labelStr);

    if (msg->length < 4 + Control_Header_SIZE) {
        Log_info(ch->log, "DROP runt ctrl packet from [%s]", labelStr);
        return NULL;
    }

    Assert_true(routeHdr.flags & RouteHeader_flags_CTRLMSG);

    if (Checksum_engine(msg->bytes, msg->length)) {
        Log_info(ch->log, "DROP ctrl packet from [%s] with invalid checksum", labelStr);
        return NULL;
    }

    struct Control* ctrl = (struct Control*) msg->bytes;

    if (ctrl->header.type_be == Control_ERROR_be) {
        return handleError(msg, ch, label, labelStr);

    } else if (ctrl->header.type_be == Control_KEYPING_be
            || ctrl->header.type_be == Control_PING_be)
    {
        return handlePing(msg, ch, label, labelStr, ctrl->header.type_be);

    } else if (ctrl->header.type_be == Control_KEYPONG_be
            || ctrl->header.type_be == Control_PONG_be)
    {
        Log_debug(ch->log, "got switch pong from [%s]", labelStr);
        Message_push(msg, &routeHdr, RouteHeader_SIZE, NULL);
        return Iface_next(&ch->pub.switchPingerIf, msg);
    }

    Log_info(ch->log, "DROP control packet of unknown type from [%s], type [%d]",
             labelStr, Endian_bigEndianToHost16(ctrl->header.type_be));

    return NULL;
}
/**
 * Handle an incoming control message from a switch.
 *
 * @param context the ducttape context.
 * @param message the control message, this should be alligned on the beginning of the content,
 *                that is to say, after the end of the switch header.
 * @param switchHeader the header.
 * @param switchIf the interface which leads to the switch.
 * @param isFormV8 true if the control message is in the form specified by protocol version 8+
 */
static Iface_DEFUN incomingFromCore(struct Message* msg, struct Iface* coreIf)
{
    struct ControlHandler_pvt* ch = Identity_check((struct ControlHandler_pvt*) coreIf);

    struct SwitchHeader switchHeader;
    Message_pop(msg, &switchHeader, SwitchHeader_SIZE, NULL);
    uint8_t labelStr[20];
    uint64_t label = Endian_bigEndianToHost64(switchHeader.label_be);
    AddrTools_printPath(labelStr, label);
    Log_debug(ch->log, "ctrl packet from [%s]", labelStr);

    if (msg->length < 4 + Control_Header_SIZE) {
        Log_info(ch->log, "DROP runt ctrl packet from [%s]", labelStr);
        return NULL;
    }

    Assert_true(Message_pop32(msg, NULL) == 0xffffffff);

    if (Checksum_engine(msg->bytes, msg->length)) {
        Log_info(ch->log, "DROP ctrl packet from [%s] with invalid checksum", labelStr);
        return NULL;
    }

    struct Control* ctrl = (struct Control*) msg->bytes;

    if (ctrl->header.type_be == Control_ERROR_be) {
        return handleError(msg, ch, label, labelStr);

    } else if (ctrl->header.type_be == Control_KEYPING_be
            || ctrl->header.type_be == Control_PING_be)
    {
        return handlePing(msg, ch, label, labelStr, ctrl->header.type_be);

    } else if (ctrl->header.type_be == Control_KEYPONG_be
            || ctrl->header.type_be == Control_PONG_be)
    {
        Log_debug(ch->log, "got switch pong from [%s]", labelStr);
        // Shift back over the header
        Message_shift(msg, 4 + SwitchHeader_SIZE, NULL);
        return Iface_next(&ch->pub.switchPingerIf, msg);
    }

    Log_info(ch->log, "DROP control packet of unknown type from [%s], type [%d]",
             labelStr, Endian_bigEndianToHost16(ctrl->header.type_be));

    return NULL;
}
Exemple #24
0
static Iface_DEFUN searchReq(struct Message* msg, struct Pathfinder_pvt* pf)
{
    uint8_t addr[16];
    Message_pop(msg, addr, 16, NULL);
    Assert_true(!msg->length);
    uint8_t printedAddr[40];
    AddrTools_printIp(printedAddr, addr);
    Log_debug(pf->log, "Search req [%s]", printedAddr);

    struct Node_Two* node = NodeStore_nodeForAddr(pf->nodeStore, addr);
    if (node) {
        onBestPathChange(pf, node);
    } else {
        SearchRunner_search(addr, 20, 3, pf->searchRunner, pf->alloc);
    }
    return NULL;
}
Exemple #25
0
static void done(struct Context* ctx)
{
    uint64_t endTimes = Time_hrtime();
    uint64_t time = (endTimes - ctx->startTime) / 1000000;

    // same as items / (time / 1024) (converting time to seconds)
    uint64_t kbps = (ctx->items * 1024) / time;

    Log_info(ctx->log, " ");
    Log_info(ctx->log, "---------------------------------------------------------------");
    Log_info(ctx->log, "Benchmark %s in %dms. %d %s per second",
        ctx->benchName, (int)time, (int)kbps, ctx->itemName);
    Log_info(ctx->log, "---------------------------------------------------------------");
    Log_info(ctx->log, " ");
    Assert_true(ctx->benchName);
    ctx->benchName = NULL;
}
Exemple #26
0
int main()
{
    struct Allocator* alloc = MallocAllocator_new(1024);
    struct Random* rand = Random_new(alloc, NULL, NULL);

    FILE* tmp = tmpfile();
    uint8_t buffer1[2048];
    size_t checkSize;
    Random_bytes(rand, buffer1, 2048);
    checkSize = fwrite(buffer1, 1, 2048, tmp);
    if (checkSize != 2048)
    {
        return 1;
    }

    uint8_t buffer2[1024];
    rewind(tmp);
    struct Reader* r = FileReader_new(tmp, alloc);

    Reader_read(r, buffer2, 128);
    Reader_skip(r, 128);
    Reader_read(r, buffer2+128, 128);
    Reader_skip(r, 512);
    Reader_read(r, buffer2+128+128, 256);
    Reader_skip(r, 300);
    Reader_read(r, buffer2+128+128+256, 128);

    Assert_true(r->bytesRead == 128+128+128+512+256+300+128);

    uint8_t* ptr1 = buffer1;
    uint8_t* ptr2 = buffer2;

    #define SKIP(x) ptr1 += x
    #define CMP(x) Assert_true(!Bits_memcmp(ptr1, ptr2, x)); ptr1 += x; ptr2 += x

    CMP(128);
    SKIP(128);
    CMP(128);
    SKIP(512);
    CMP(256);
    SKIP(300);
    CMP(128);

    Allocator_free(alloc);
    return 0;
}
Exemple #27
0
static struct Address* getBest(struct RumorMill_pvt* rm)
{
    if (rm->pub.count == 0) {
        return NULL;
    }
    struct Address* best = NULL;
    int howBadIsTheBest = -1;
    for (int i = 0; i < rm->pub.count; i++) {
        int howBad = getBadness(&rm->pub.addresses[i], rm->selfAddr);
        if (howBad < howBadIsTheBest || !best) {
            howBadIsTheBest = howBad;
            best = &rm->pub.addresses[i];
        }
    }
    Assert_true(best);
    return best;
}
Exemple #28
0
// only in parent
static void inFromChildSkipMmsg(struct Admin* admin)
{
    Assert_true(admin->messageHeader.length > 0);
    uint8_t buffer[MAX_MESSAGE_SIZE];
    uint32_t have = 0;

    int amount = inFromChildFillBuffer(admin, buffer, MAX_MESSAGE_SIZE,
                                       &have, admin->messageHeader.length);
    if (amount < 0) {
        return;
    }

    admin->messageHeader.length -= amount;
    if (0 == admin->messageHeader.length) {
        admin->haveMessageHeaderLen = 0;
    }
}
Exemple #29
0
static inline uint8_t encryptMessage(struct Message* message,
                                     struct CryptoAuth_Wrapper* wrapper)
{
    Assert_true(message->padding >= 36 || !"not enough padding");

    encrypt(wrapper->nextNonce,
            message,
            wrapper->sharedSecret,
            wrapper->isInitiator);

    Message_shift(message, 4, NULL);

    union Headers_CryptoAuth* header = (union Headers_CryptoAuth*) message->bytes;
    header->nonce = Endian_hostToBigEndian32(wrapper->nextNonce);
    wrapper->nextNonce++;

    return wrapper->wrappedInterface->sendMessage(message, wrapper->wrappedInterface);
}
Exemple #30
0
static void onReply(Dict* msg, struct Address* src, struct MsgCore_Promise* prom)
{
    struct ReachabilityCollector_pvt* rcp =
        Identity_check((struct ReachabilityCollector_pvt*) prom->userData);
    Assert_true(prom == rcp->msgOnWire);
    if (!src) {
        onReplyTimeout(prom);
        mkNextRequest(rcp);
        return;
    }
    struct Address_List* results = ReplySerializer_parse(src, msg, rcp->log, false, prom->alloc);
    uint64_t path = 1;

    struct PeerInfo* pi = NULL;
    for (int j = 0; j < rcp->piList->length; j++) {
        struct PeerInfo* pi0 = ArrayList_OfPeerInfo_get(rcp->piList, j);
        if (Address_isSameIp(&pi0->addr, src)) {
            pi = pi0;
            break;
        }
    }
    if (!pi) {
        Log_debug(rcp->log, "Got message from peer which is gone from list");
        return;
    }

    for (int i = 0; i < results->length; i++) {
        path = results->elems[i].path;
        if (Bits_memcmp(results->elems[i].ip6.bytes, rcp->myAddr->ip6.bytes, 16)) { continue; }
        if (pi->pathThemToUs != path) {
            Log_debug(rcp->log, "Found back-route for [%s]",
                Address_toString(src, prom->alloc)->bytes);
            if (rcp->pub.onChange) {
                rcp->pub.onChange(
                    &rcp->pub, src->ip6.bytes, path, src->path, 0, 0xffff, 0xffff, 0xffff);
            }
        }
        pi->pathThemToUs = path;
        pi->querying = false;
        return;
    }
    pi->pathToCheck = (results->length < 8) ? 1 : path;
    mkNextRequest(rcp);
}