コード例 #1
0
ファイル: IpTunnel_test.c プロジェクト: DmytroOrlov/cjdns
static bool trySend6(struct Allocator* alloc,
                     uint64_t addrHigh,
                     uint64_t addrLow,
                     struct Iface* sendTo,
                     struct Context* ctx)
{
    struct Message* msg6 = Message_new(0, 512, alloc);
    Message_push(msg6, "hello world", 12, NULL);
    Message_push(msg6, NULL, Headers_IP6Header_SIZE, NULL);
    struct Headers_IP6Header* iph = (struct Headers_IP6Header*) msg6->bytes;
    Headers_setIpVersion(iph);
    uint64_t addrHigh_be = Endian_hostToBigEndian64(addrHigh);
    uint64_t addrLow_be = Endian_hostToBigEndian64(addrLow);
    Bits_memcpy(iph->sourceAddr, &addrHigh_be, 8);
    Bits_memcpy(&iph->sourceAddr[8], &addrLow_be, 8);
    Bits_memcpy(ctx->sendingAddress, iph->sourceAddr, 16);
    uint8_t destAddr[16] = { 20, 01 };
    destAddr[15] = 1;
    Bits_memcpy(iph->destinationAddr, destAddr, 16);
    pushRouteDataHeaders(ctx, msg6);
    Iface_send(sendTo, msg6);
    if (ctx->called == 4) {
        ctx->called = 0;
        return true;
    }
    Assert_true(ctx->called == 0);
    return false;
}
コード例 #2
0
ファイル: InterfaceController.c プロジェクト: Kubuxu/cjdns
static void sendBeacon(struct InterfaceController_Iface_pvt* ici, struct Allocator* tempAlloc)
{
    if (ici->beaconState < InterfaceController_beaconState_newState_SEND) {
        Log_debug(ici->ic->logger, "sendBeacon(%s) -> beaconing disabled", ici->name->bytes);
        return;
    }

    Log_debug(ici->ic->logger, "sendBeacon(%s)", ici->name->bytes);

    struct Message* msg = Message_new(0, 128, tempAlloc);
    Message_push(msg, &ici->ic->beacon, Headers_Beacon_SIZE, NULL);

    if (Defined(Log_DEBUG)) {
        char* content = Hex_print(msg->bytes, msg->length, tempAlloc);
        Log_debug(ici->ic->logger, "SEND BEACON CONTENT[%s]", content);
    }

    struct Sockaddr sa = {
        .addrLen = Sockaddr_OVERHEAD,
        .flags = Sockaddr_flags_BCAST
    };
    Message_push(msg, &sa, Sockaddr_OVERHEAD, NULL);

    Iface_send(&ici->pub.addrIf, msg);
}
コード例 #3
0
ファイル: CryptoAuth_unit_test.c プロジェクト: cmotc/cjdns
static void repeatHello()
{
    uint8_t* expectedOutput =
        "0000000101641c99f7719f5700000000a693a9fd3f0e27e81ab1100b57b37259"
        "4c2adca8671f1fdd050383c91e7d56ec2336c09739fa8e91d8dc5bec63e8fad0"
        "74bee22a90642a6ba8555be84c5e35970c5270e8f31f2a5978e0fbdee4542882"
        "97568f25a3fc2801aa707d954c78eccb970bcc8cb26867e9dbf0c9d6ef1b3f27"
        "24e7e550";

    struct Allocator* alloc = MallocAllocator_new(1<<20);
    struct Context* ctx = setUp(NULL, HERPUBKEY, "password", alloc);
    struct Message* msg = Message_new(0, CryptoHeader_SIZE + HELLOWORLDLEN, alloc);
    Message_push(msg, HELLOWORLD, HELLOWORLDLEN, NULL);

    Assert_true(!CryptoAuth_encrypt(ctx->sess, msg));

    Message_reset(msg);
    Message_push(msg, HELLOWORLD, HELLOWORLDLEN, NULL);

    Assert_true(!CryptoAuth_encrypt(ctx->sess, msg));

    char* actual = Hex_print(msg->bytes, msg->length, alloc);
    if (CString_strcmp(actual, expectedOutput)) {
        Assert_failure("Test failed.\n"
                       "Expected %s\n"
                       "     Got %s\n", expectedOutput, actual);
    }
    Allocator_free(alloc);
}
コード例 #4
0
ファイル: MsgCore.c プロジェクト: sssemil/cjdns
static void sendMsg(struct MsgCore_pvt* mcp,
                    Dict* msgDict,
                    struct Address* addr,
                    struct Allocator* allocator)
{
    struct Allocator* alloc = Allocator_child(allocator);

    // Send the encoding scheme definition
    Dict_putString(msgDict, CJDHTConstants_ENC_SCHEME, mcp->schemeDefinition, allocator);

    // And tell the asker which interface the message came from
    int encIdx = EncodingScheme_getFormNum(mcp->scheme, addr->path);
    Assert_true(encIdx != EncodingScheme_getFormNum_INVALID);
    Dict_putInt(msgDict, CJDHTConstants_ENC_INDEX, encIdx, allocator);

    // send the protocol version
    Dict_putInt(msgDict, CJDHTConstants_PROTOCOL, Version_CURRENT_PROTOCOL, allocator);

    if (!Defined(SUBNODE)) {
        String* q = Dict_getStringC(msgDict, "q");
        String* sq = Dict_getStringC(msgDict, "sq");
        if (q || sq) {
            Log_debug(mcp->log, "Send query [%s] to [%s]",
                ((q) ? q->bytes : sq->bytes),
                Address_toString(addr, alloc)->bytes);
            String* txid = Dict_getStringC(msgDict, "txid");
            Assert_true(txid);
            String* newTxid = String_newBinary(NULL, txid->len + 1, alloc);
            Bits_memcpy(&newTxid->bytes[1], txid->bytes, txid->len);
            newTxid->bytes[0] = '1';
            Dict_putStringC(msgDict, "txid", newTxid, alloc);
        }
    }

    struct Message* msg = Message_new(0, 2048, alloc);
    BencMessageWriter_write(msgDict, msg, NULL);

    //Log_debug(mcp->log, "Sending msg [%s]", Escape_getEscaped(msg->bytes, msg->length, alloc));

    // Sanity check (make sure the addr was actually calculated)
    Assert_true(addr->ip6.bytes[0] == 0xfc);

    struct DataHeader data;
    Bits_memset(&data, 0, sizeof(struct DataHeader));
    DataHeader_setVersion(&data, DataHeader_CURRENT_VERSION);
    DataHeader_setContentType(&data, ContentType_CJDHT);
    Message_push(msg, &data, sizeof(struct DataHeader), NULL);

    struct RouteHeader route;
    Bits_memset(&route, 0, sizeof(struct RouteHeader));
    Bits_memcpy(route.ip6, addr->ip6.bytes, 16);
    route.version_be = Endian_hostToBigEndian32(addr->protocolVersion);
    route.sh.label_be = Endian_hostToBigEndian64(addr->path);
    Bits_memcpy(route.publicKey, addr->key, 32);
    Message_push(msg, &route, sizeof(struct RouteHeader), NULL);

    Iface_send(&mcp->pub.interRouterIf, msg);
}
コード例 #5
0
ファイル: TUNTools.c プロジェクト: 0x20c24/cjdns
static void sendHello(void* vctx)
{
    struct TUNTools_pvt* ctx = Identity_check((struct TUNTools_pvt*) vctx);
    struct Message* msg;
    Message_STACK(msg, 0, 64);
    Message_push(msg, "Hello World", 12, NULL);
    Message_push(msg, ctx->dest, ctx->dest->addrLen, NULL);
    Interface_sendMessage(&ctx->iface->generic, msg);
}
コード例 #6
0
ファイル: TUNTools.c プロジェクト: BurnBeforeReading/cjdns
static void sendHello(void* vctx)
{
    struct TUNTools_pvt* ctx = Identity_check((struct TUNTools_pvt*) vctx);
    struct Allocator* tempAlloc = Allocator_child(ctx->pub.alloc);
    struct Message* msg = Message_new(0, 64, tempAlloc);
    Message_push(msg, "Hello World", 12, NULL);
    Message_push(msg, ctx->pub.tunDestAddr, ctx->pub.tunDestAddr->addrLen, NULL);
    Iface_send(&ctx->pub.udpIface, msg);
    Allocator_free(tempAlloc);
}
コード例 #7
0
ファイル: MultiInterface_test.c プロジェクト: Arceliar/cjdns
int main()
{
    struct Allocator* alloc = MallocAllocator_new(1<<20);
    struct Random* rand = Random_new(alloc, NULL, NULL);

    // mock interface controller.
    struct Context ctx = {
        .ic = {
            .registerPeer = registerPeer,
            .getPeerState = getPeerState
        }
    };

    struct Interface externalIf = {
        .sendMessage = sendMessage,
        .allocator = alloc,
        .senderContext = &ctx
    };

    /*struct MultiInterface* mif = */MultiInterface_new(KEY_SIZE, &externalIf, &ctx.ic);

    struct Entry* entries = Allocator_malloc(alloc, sizeof(struct Entry) * ENTRY_COUNT);
    Random_bytes(rand, (uint8_t*)entries, ENTRY_COUNT * sizeof(struct Entry));

    struct Interface** ifaces = Allocator_calloc(alloc, sizeof(char*), ENTRY_COUNT);

    // seed the list with some near collisions.
    for (int i = 0; i < 10; i++) {
        int rnd = (((uint32_t*)entries)[i] >> 1) % ENTRY_COUNT;
        ((uint32_t*) (&entries[rnd]))[0] = ((uint32_t*) (&entries[i]))[0];
    }

    for (int i = 0; i < CYCLES; i++) {
        int rnd = ((uint32_t*)entries)[i] % ENTRY_COUNT;
        struct Entry* entry = &entries[rnd];
        struct Interface* iface = ifaces[rnd];

        struct Message* msg;
        Message_STACK(msg, 0, 128);

        Message_push(msg, "hello world", 12);
        Message_push(msg, entry, 16);

        externalIf.receiveMessage(msg, &externalIf);

        //printf("Received message for iface [%u] from [%p]\n", rnd, (void*)ctx.receivedOn);
        if (iface) {
            Assert_always(ctx.receivedOn == iface);
        } else {
            ifaces[rnd] = ctx.receivedOn;
        }
    }

    Allocator_free(alloc);
}
コード例 #8
0
int main(int argc, char** argv)
{
    struct Allocator* alloc = MallocAllocator_new(1<<20);
    struct EventBase* base = EventBase_new(alloc);
    struct Writer* logWriter = FileWriter_new(stdout, alloc);
    struct Log* logger = WriterLog_new(logWriter, alloc);

    struct Sockaddr* addrA = Sockaddr_fromBytes(testAddrA, Sockaddr_AF_INET6, alloc);

    char assignedIfName[TUNInterface_IFNAMSIZ];
    struct Interface* tun = TUNInterface_new(NULL, assignedIfName, base, logger, NULL, alloc);
    NetDev_addAddress(assignedIfName, addrA, 126, logger, NULL);

    struct Sockaddr_storage addr;
    Assert_always(!Sockaddr_parse("[fd00::1]", &addr));

    #ifdef freebsd
        // tun is not setup synchronously in bsd but it lets you bind to the tun's
        // address anyway.
        sleep(1);
    #endif

    // 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 = setupUDP(base, &addr.addr, alloc, logger))) {
            break;
        }
    }
    Assert_always(udp);

    struct Sockaddr* dest = Sockaddr_clone(udp->addr, alloc);
    uint8_t* addrBytes;
    Assert_always(16 == Sockaddr_getAddress(dest, &addrBytes));
    Bits_memcpy(addrBytes, testAddrB, 16);

    struct Message* msg;
    Message_STACK(msg, 0, 64);
    Message_push(msg, "Hello World", 12, NULL);
    Message_push(msg, dest, dest->addrLen, NULL);

    udp->generic.receiveMessage = receiveMessageUDP;
    udp->generic.receiverContext = alloc;
    tun->receiveMessage = receiveMessageTUN;

    udp->generic.sendMessage(msg, &udp->generic);

    Timeout_setTimeout(fail, NULL, 10000, base, alloc);

    EventBase_beginLoop(base);
    return 0;
}
コード例 #9
0
ファイル: Sign_test.c プロジェクト: cjdelisle/cjdns
int main()
{
    struct Allocator* alloc = MallocAllocator_new(1048576);
    struct Log* logger = FileWriterLog_new(stdout, alloc);
    struct Random* rand = Random_new(alloc, logger, NULL);

    uint8_t curve25519private[32];
    Random_bytes(rand, curve25519private, 32);
    uint8_t curve25519public[32];
    crypto_scalarmult_curve25519_base(curve25519public, curve25519private);

    uint8_t signingKeyPair[64];
    Sign_signingKeyPairFromCurve25519(signingKeyPair, curve25519private);
    struct Message* msg = Message_new(0, 512, alloc);
    Message_push(msg, "hello world", 12, NULL);
    Sign_signMsg(signingKeyPair, msg, rand);

    uint8_t curve25519publicB[32];
    Assert_true(!Sign_verifyMsg(&signingKeyPair[32], msg));
    Assert_true(!Sign_publicSigningKeyToCurve25519(curve25519publicB, &signingKeyPair[32]));
    Assert_true(!Bits_memcmp(curve25519publicB, curve25519public, 32));

    Allocator_free(alloc);
    return 0;
}
コード例 #10
0
ファイル: InterfaceController.c プロジェクト: Kubuxu/cjdns
// This is directly called from SwitchCore, message is not encrypted.
static Iface_DEFUN sendFromSwitch(struct Message* msg, struct Iface* switchIf)
{
    struct Peer* ep = Identity_check((struct Peer*) switchIf);

    ep->bytesOut += msg->length;

    int msgs = PeerLink_send(msg, ep->peerLink);

    for (int i = 0; i < msgs; i++) {
        msg = PeerLink_poll(ep->peerLink);
        Assert_true(!CryptoAuth_encrypt(ep->caSession, msg));

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

        // push the lladdr...
        Message_push(msg, ep->lladdr, ep->lladdr->addrLen, NULL);

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

        Iface_send(&ep->ici->pub.addrIf, msg);
    }
    return NULL;
}
コード例 #11
0
ファイル: Sign.c プロジェクト: benhylau/cjdns
void Sign_signMsg(uint8_t keyPair[64], struct Message* msg, struct Random* rand)
{
    // az is set to the secret key followed by another secret value
    // which since we don't have a secret seed in this algorithm is just the
    // hash of the secret key and 32 bytes of random
    uint8_t az[64];
    uint8_t r[64];
    ge_p3 R;
    uint8_t hram[64];

    Bits_memcpy(az, keyPair, 32);
    Random_bytes(rand, &az[32], 32);
    crypto_hash_sha512(az,az,64);
    Bits_memcpy(az, keyPair, 32);
    az[0] &= 248;
    az[31] &= 63;
    az[31] |= 64;

    // hash message + secret number
    Message_push(msg, &az[32], 32, NULL);
    crypto_hash_sha512(r, msg->bytes, msg->length);

    // Replace secret number with public key
    Bits_memcpy(msg->bytes, &keyPair[32], 32);

    // push pointMul(r) to message
    sc_reduce(r);
    ge_scalarmult_base(&R,r);
    Message_shift(msg, 32, NULL);
    ge_p3_tobytes(msg->bytes,&R);

    crypto_hash_sha512(hram, msg->bytes, msg->length);
    sc_reduce(hram);
    sc_muladd(&msg->bytes[32], hram, az, r);
}
コード例 #12
0
ファイル: AddrInterfaceAdapter.c プロジェクト: AdUser/cjdns
static uint8_t receiveMessage(struct Message* message, struct Interface* iface)
{
    struct AddrInterfaceAdapter_pvt* context =
        Identity_cast((struct AddrInterfaceAdapter_pvt*) iface->receiverContext);

    Message_push(message, context->pub.addr, context->pub.addr->addrLen, NULL);
    return Interface_receiveMessage(&context->pub.generic, message);
}
コード例 #13
0
ファイル: Ducttape.c プロジェクト: lgierth/cjdns
static inline uint8_t incomingDHT(struct Message* message,
                                  struct Address* addr,
                                  struct Ducttape_pvt* context)
{
    struct DHTMessage dht = {
        .address = addr,
        .binMessage = message,
        .allocator = message->alloc
    };

    DHTModuleRegistry_handleIncoming(&dht, context->registry);

    // TODO(cjd): return something meaningful.
    return Error_NONE;
}

/** Header must not be encrypted and must be aligned on the beginning of the ipv6 header. */
static inline uint8_t sendToRouter(struct Message* message,
                                   struct Ducttape_MessageHeader* dtHeader,
                                   struct SessionManager_Session* session,
                                   struct Ducttape_pvt* context)
{
    int safeDistance = SwitchHeader_SIZE;

    CryptoAuth_resetIfTimeout(session->internal);
    if (CryptoAuth_getState(session->internal) < CryptoAuth_HANDSHAKE3) {
        // Put the handle into the message so that it's authenticated.
        // see: sendToSwitch()
        //Log_debug(context->logger, "Sending receive handle under CryptoAuth");
        Message_push(message, &session->receiveHandle_be, 4, NULL);

        safeDistance += CryptoHeader_SIZE;
    } else {
        // 16 for the authenticator, 4 for the nonce and 4 for the handle
        safeDistance += 24;
    }

    Message_shift(message, safeDistance, NULL);
    if (dtHeader->switchHeader) {
        if (message->bytes != (uint8_t*)dtHeader->switchHeader) {
            Bits_memmoveConst(message->bytes, dtHeader->switchHeader, SwitchHeader_SIZE);
            dtHeader->switchHeader = (struct SwitchHeader*) message->bytes;
        }
    } else {
        dtHeader->switchHeader = (struct SwitchHeader*) message->bytes;
        Bits_memset(dtHeader->switchHeader, 0, SwitchHeader_SIZE);
    }
    Message_shift(message, -safeDistance, NULL);

    SwitchHeader_setVersion(dtHeader->switchHeader, SwitchHeader_CURRENT_VERSION);
    SwitchHeader_setLabelShift(dtHeader->switchHeader, 0);
    dtHeader->switchHeader->label_be = Endian_hostToBigEndian64(dtHeader->switchLabel);

    // This comes out in outgoingFromCryptoAuth() then sendToSwitch()
    dtHeader->receiveHandle = Endian_bigEndianToHost32(session->receiveHandle_be);
    dtHeader->layer = Ducttape_SessionLayer_OUTER;
    return Interface_sendMessage(session->internal, message);
}
コード例 #14
0
int main(int argc, char** argv)
{
    // TODO: fix TUNConfigurator_addIp4Address() for Illumos, Darwin, BSD.
    #if defined(Illumos) || defined(Darwin) || defined(FreeBSD) || defined(OpenBSD)
        return 0;
    #endif

    struct Allocator* alloc = MallocAllocator_new(1<<20);
    struct EventBase* base = EventBase_new(alloc);
    struct Writer* logWriter = FileWriter_new(stdout, alloc);
    struct Log* logger = WriterLog_new(logWriter, alloc);

    struct Sockaddr* addrA = Sockaddr_fromBytes(testAddrA, Sockaddr_AF_INET, alloc);

    char assignedIfName[TUNInterface_IFNAMSIZ];
    struct Interface* tun = TUNInterface_new(NULL, assignedIfName, base, logger, NULL, alloc);
    NetDev_addAddress(assignedIfName, addrA, 30, logger, NULL);

    struct Sockaddr_storage ss;
    Assert_true(!Sockaddr_parse("0.0.0.0", &ss));
    struct AddrInterface* udp = UDPAddrInterface_new(base, &ss.addr, alloc, NULL, logger);

    struct Sockaddr* dest = Sockaddr_clone(udp->addr, alloc);
    uint8_t* addr;
    Assert_true(4 == Sockaddr_getAddress(dest, &addr));
    Bits_memcpy(addr, testAddrB, 4);

    struct Message* msg;
    Message_STACK(msg, 0, 64);
    Message_push(msg, "Hello World", 12);
    Message_push(msg, dest, dest->addrLen);

    udp->generic.receiveMessage = receiveMessageUDP;
    udp->generic.receiverContext = alloc;
    tun->receiveMessage = receiveMessageTUN;

    udp->generic.sendMessage(msg, &udp->generic);

    Timeout_setTimeout(fail, NULL, 1000, base, alloc);

    EventBase_beginLoop(base);
}
コード例 #15
0
int main(int argc, char** argv)
{
    struct Allocator* alloc = MallocAllocator_new(1<<20);
    struct EventBase* base = EventBase_new(alloc);
    struct Writer* logWriter = FileWriter_new(stdout, alloc);
    struct Log* logger = WriterLog_new(logWriter, alloc);

    // mock interface controller.
    struct InterfaceController ic = {
        .registerPeer = registerPeer
    };

    struct Sockaddr_storage addr;
    Assert_always(!Sockaddr_parse("127.0.0.1", &addr));

    struct UDPInterface* udpA = UDPInterface_new(base, &addr.addr, alloc, NULL, logger, &ic);
    struct UDPInterface* udpB = UDPInterface_new(base, &addr.addr, alloc, NULL, logger, &ic);

    struct Message* msg;
    Message_STACK(msg, 0, 128);

    Message_push(msg, "Hello World", 12, NULL);
    Message_push(msg, udpA->addr, udpA->addr->addrLen, NULL);

    struct Interface* ifA = &((struct UDPInterface_pvt*) udpA)->udpBase->generic;
    struct Interface* ifB = &((struct UDPInterface_pvt*) udpB)->udpBase->generic;

    ifA->receiveMessage = receiveMessageA;
    ifB->receiveMessage = receiveMessageB;
    ifB->receiverContext = alloc;

    struct Allocator* child = Allocator_child(alloc);
    msg = Message_clone(msg, child);
    ifB->sendMessage(msg, ifB);
    Allocator_free(child);

    Timeout_setTimeout(fail, NULL, 1000, base, alloc);

    EventBase_beginLoop(base);
    return 0;
}
コード例 #16
0
ファイル: UDPAddrInterface.c プロジェクト: CSRedRat/cjdns
static void handleEvent(void* vcontext)
{
    struct UDPAddrInterface_pvt* context = (struct UDPAddrInterface_pvt*) vcontext;

    struct Message message = {
        .bytes = context->messageBuff.content,
        .padding = UDPAddrInterface_PADDING,
        .length = UDPAddrInterface_MAX_PACKET_SIZE
    };

    struct Sockaddr_storage addrStore;

    int rc = Socket_recvfrom(context->socket,
                             message.bytes,
                             message.length,
                             0,
                             &addrStore);

    if (rc < 0) {
        return;
    }
    if (addrStore.addr.addrLen != context->pub.addr->addrLen) {
        return;
    }
    message.length = rc;

    Message_push(&message, &addrStore, addrStore.addr.addrLen);

    if (context->pub.generic.receiveMessage) {
        context->pub.generic.receiveMessage(&message, &context->pub.generic);
    }
}

struct AddrInterface* UDPAddrInterface_new(struct EventBase* base,
                                           struct Sockaddr* addr,
                                           struct Allocator* allocator,
                                           struct Except* exHandler,
                                           struct Log* logger)
{
    struct UDPAddrInterface_pvt* context =
        Allocator_malloc(allocator, sizeof(struct UDPAddrInterface_pvt));

    Bits_memcpyConst(context, (&(struct UDPAddrInterface_pvt) {
        .pub = {
            .generic = {
                .sendMessage = sendMessage,
                .senderContext = context,
                .allocator = allocator
            },
        },
        .logger = logger,
        .socket = -1
    }), sizeof(struct UDPAddrInterface_pvt));
コード例 #17
0
ファイル: IpTunnel_test.c プロジェクト: DmytroOrlov/cjdns
static bool trySend4(struct Allocator* alloc,
                     uint32_t addr,
                     struct Iface* sendTo,
                     struct Context* ctx)
{
    struct Message* msg4 = Message_new(0, 512, alloc);
    Message_push(msg4, "hello world", 12, NULL);
    Message_push(msg4, NULL, Headers_IP4Header_SIZE, NULL);
    struct Headers_IP4Header* iph = (struct Headers_IP4Header*) msg4->bytes;
    Headers_setIpVersion(iph);
    uint32_t addr_be = Endian_hostToBigEndian32(addr);
    Bits_memcpy(iph->sourceAddr, &addr_be, 4);
    Bits_memcpy(ctx->sendingAddress, &addr_be, 4);
    Bits_memcpy(iph->destAddr, ((uint8_t[]){ 11, 0, 0, 1 }), 4);
    pushRouteDataHeaders(ctx, msg4);
    Iface_send(sendTo, msg4);
    if (ctx->called == 1) {
        ctx->called = 0;
        return true;
    }
    Assert_true(ctx->called == 0);
    return false;
}
コード例 #18
0
ファイル: ETHInterface_Linux.c プロジェクト: Arceliar/cjdns
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;
}
コード例 #19
0
ファイル: Ducttape.c プロジェクト: wpapper/cjdns
/** Header must not be encrypted and must be aligned on the beginning of the ipv6 header. */
static inline uint8_t sendToRouter(struct Message* message,
                                   struct Ducttape_MessageHeader* dtHeader,
                                   struct SessionManager_Session* session,
                                   struct Ducttape_pvt* context)
{
    int safeDistance = Headers_SwitchHeader_SIZE;

    if (CryptoAuth_getState(&session->iface) < CryptoAuth_HANDSHAKE3) {
        // Bug 104, see Version.h
        #ifdef Version_2_COMPAT
        if (session->version >= 3) {
        #endif
            // Put the handle into the message so that it's authenticated.
            // see: sendToSwitch()
            Log_debug(context->logger, "Sending receive handle under CryptoAuth");
            Message_push(message, &session->receiveHandle_be, 4);
        #ifdef Version_2_COMPAT
        } else {
            // Otherwise it will be added on the other side.
            safeDistance += 4;
        }
        #endif

        safeDistance += Headers_CryptoAuth_SIZE;
    } else {
        // 16 for the authenticator, 4 for the nonce and 4 for the handle
        safeDistance += 24;
    }

    Message_shift(message, safeDistance);
    if (dtHeader->switchHeader) {
        if (message->bytes != (uint8_t*)dtHeader->switchHeader) {
            Bits_memmoveConst(message->bytes, dtHeader->switchHeader, Headers_SwitchHeader_SIZE);
            dtHeader->switchHeader = (struct Headers_SwitchHeader*) message->bytes;
        }
    } else {
        dtHeader->switchHeader = (struct Headers_SwitchHeader*) message->bytes;
        Bits_memset(dtHeader->switchHeader, 0, Headers_SwitchHeader_SIZE);
    }
    Message_shift(message, -safeDistance);

    dtHeader->switchHeader->label_be = Endian_hostToBigEndian64(dtHeader->switchLabel);


    // This comes out in outgoingFromCryptoAuth() then sendToSwitch()
    dtHeader->receiveHandle = Endian_bigEndianToHost32(session->receiveHandle_be);
    dtHeader->layer = Ducttape_SessionLayer_OUTER;
    return session->iface.sendMessage(message, &session->iface);
}
コード例 #20
0
ファイル: NDPServer.c プロジェクト: AdUser/cjdns
static int sendResponse(struct Message* msg,
                        struct Ethernet* eth,
                        struct Headers_IP6Header* ip6,
                        struct NDPServer_pvt* ns)
{
    Bits_memcpyConst(ip6->destinationAddr, ip6->sourceAddr, 16);
    Bits_memcpyConst(ip6->sourceAddr, UNICAST_ADDR, 16);
    ip6->hopLimit = 255;

    struct NDPHeader_RouterAdvert* adv = (struct NDPHeader_RouterAdvert*) msg->bytes;
    adv->checksum = Checksum_icmp6(ip6->sourceAddr, msg->bytes, msg->length);

    Message_push(msg, ip6, sizeof(struct Headers_IP6Header), NULL);

    // Eth
    Message_push(msg, eth, sizeof(struct Ethernet), NULL);
    struct Ethernet* ethP = (struct Ethernet*) msg->bytes;
    Bits_memcpyConst(ethP->destAddr, eth->srcAddr, 6);
    Bits_memcpyConst(ethP->srcAddr, eth->destAddr, 6);

printf("responding\n");
    Interface_sendMessage(ns->wrapped, msg);
    return 1;
}
コード例 #21
0
ファイル: ControlHandler.c プロジェクト: interfect/cjdns
/**
 * 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;
}
コード例 #22
0
ファイル: TAPWrapper.c プロジェクト: FSFTN/cjdns
static Iface_DEFUN sendMessage(struct Message* msg, struct Iface* internal)
{
    struct TAPWrapper_pvt* tw = Identity_containerOf(internal, struct TAPWrapper_pvt, pub.internal);

    uint16_t etherType = TUNMessageType_pop(msg, NULL);
    struct Ethernet eth = { .ethertype = etherType };
    Bits_memcpyConst(eth.srcAddr, TAPWrapper_LOCAL_MAC, Ethernet_ADDRLEN);
    Bits_memcpyConst(eth.destAddr, tw->pub.peerAddress, Ethernet_ADDRLEN);
    if (Bits_isZero(tw->pub.peerAddress, Ethernet_ADDRLEN)) {
        Log_debug(tw->log, "DROP Packet because peers MAC is not yet known");
        return NULL;
    }

    Message_push(msg, &eth, sizeof(struct Ethernet), NULL);

    // struct Ethernet contains 2 bytes of padding at the beginning.
    Message_shift(msg, -2, NULL);

    return Iface_next(&tw->external, msg);
}
コード例 #23
0
ファイル: Pathfinder.c プロジェクト: cjdelisle/cjdns
static Iface_DEFUN incomingMsg(struct Message* msg, struct Pathfinder_pvt* pf)
{
    struct Address addr;
    struct RouteHeader* hdr = (struct RouteHeader*) msg->bytes;
    Message_shift(msg, -(RouteHeader_SIZE + DataHeader_SIZE), NULL);
    Bits_memcpy(addr.ip6.bytes, hdr->ip6, 16);
    Bits_memcpy(addr.key, hdr->publicKey, 32);
    addr.protocolVersion = Endian_bigEndianToHost32(hdr->version_be);
    addr.padding = 0;
    addr.path = Endian_bigEndianToHost64(hdr->sh.label_be);

    //Log_debug(pf->log, "Incoming DHT");

    struct DHTMessage dht = {
        .address = &addr,
        .binMessage = msg,
        .allocator = msg->alloc
    };

    DHTModuleRegistry_handleIncoming(&dht, pf->registry);

    struct Message* nodeMsg = Message_new(0, 256, msg->alloc);
    Iface_CALL(sendNode, nodeMsg, &addr, 0xfffffff0u, pf);

    if (dht.pleaseRespond) {
        // what a beautiful hack, see incomingFromDHT
        return Iface_next(&pf->pub.eventIf, msg);
    }

    return NULL;
}

static Iface_DEFUN incomingFromEventIf(struct Message* msg, struct Iface* eventIf)
{
    struct Pathfinder_pvt* pf = Identity_containerOf(eventIf, struct Pathfinder_pvt, pub.eventIf);
    enum PFChan_Core ev = Message_pop32(msg, NULL);
    if (Pathfinder_pvt_state_INITIALIZING == pf->state) {
        Assert_true(ev == PFChan_Core_CONNECT);
        return connected(pf, msg);
    }
    // Let the PF send another 128 path changes again because it's basically a new tick.
    pf->bestPathChanges = 0;
    switch (ev) {
        case PFChan_Core_SWITCH_ERR: return switchErr(msg, pf);
        case PFChan_Core_SEARCH_REQ: return searchReq(msg, pf);
        case PFChan_Core_PEER: return peer(msg, pf);
        case PFChan_Core_PEER_GONE: return peerGone(msg, pf);
        case PFChan_Core_SESSION: return session(msg, pf);
        case PFChan_Core_SESSION_ENDED: return sessionEnded(msg, pf);
        case PFChan_Core_DISCOVERED_PATH: return discoveredPath(msg, pf);
        case PFChan_Core_MSG: return incomingMsg(msg, pf);
        case PFChan_Core_PING: return handlePing(msg, pf);
        case PFChan_Core_PONG: return handlePong(msg, pf);
        case PFChan_Core_UNSETUP_SESSION:
        case PFChan_Core_LINK_STATE:
        case PFChan_Core_CTRL_MSG: return NULL;
        default:;
    }
    Assert_failure("unexpected event [%d]", ev);
}

static void sendEvent(struct Pathfinder_pvt* pf, enum PFChan_Pathfinder ev, void* data, int size)
{
    struct Allocator* alloc = Allocator_child(pf->alloc);
    struct Message* msg = Message_new(0, 512+size, alloc);
    Message_push(msg, data, size, NULL);
    Message_push32(msg, ev, NULL);
    Iface_send(&pf->pub.eventIf, msg);
    Allocator_free(alloc);
}

static void init(void* vpf)
{
    struct Pathfinder_pvt* pf = Identity_check((struct Pathfinder_pvt*) vpf);
    struct PFChan_Pathfinder_Connect conn = {
        .superiority_be = Endian_hostToBigEndian32(1),
        .version_be = Endian_hostToBigEndian32(Version_CURRENT_PROTOCOL)
    };
    CString_strncpy(conn.userAgent, "Cjdns internal pathfinder", 64);
    sendEvent(pf, PFChan_Pathfinder_CONNECT, &conn, PFChan_Pathfinder_Connect_SIZE);
}

struct Pathfinder* Pathfinder_register(struct Allocator* allocator,
                                       struct Log* log,
                                       struct EventBase* base,
                                       struct Random* rand,
                                       struct Admin* admin)
{
    struct Allocator* alloc = Allocator_child(allocator);
    struct Pathfinder_pvt* pf = Allocator_calloc(alloc, sizeof(struct Pathfinder_pvt), 1);
    Identity_set(pf);
    pf->alloc = alloc;
    pf->log = log;
    pf->base = base;
    pf->rand = rand;
    pf->admin = admin;

    pf->pub.eventIf.send = incomingFromEventIf;

    pf->dhtModule.context = pf;
    pf->dhtModule.handleOutgoing = incomingFromDHT;

    // This needs to be done asynchronously so the pf can be plumbed to the core
    Timeout_setTimeout(init, pf, 0, base, alloc);

    return &pf->pub;
}
コード例 #24
0
ファイル: ETHInterface_linux.c プロジェクト: wfleurant/cjdns
static Iface_DEFUN sendMessage(struct Message* msg, struct Iface* iface)
{
    struct ETHInterface_pvt* ctx =
        Identity_containerOf(iface, struct ETHInterface_pvt, pub.generic.iface);

    struct Sockaddr* sa = (struct Sockaddr*) msg->bytes;
    Assert_true(msg->length >= Sockaddr_OVERHEAD);
    Assert_true(sa->addrLen <= ETHInterface_Sockaddr_SIZE);

    struct ETHInterface_Sockaddr sockaddr = { .generic = { .addrLen = 0 } };
    Message_pop(msg, &sockaddr, sa->addrLen, NULL);

    struct sockaddr_ll addr;
    Bits_memcpy(&addr, &ctx->addrBase, sizeof(struct sockaddr_ll));

    if (sockaddr.generic.flags & Sockaddr_flags_BCAST) {
        Bits_memset(addr.sll_addr, 0xff, 6);
    } else {
        Bits_memcpy(addr.sll_addr, sockaddr.mac, 6);
    }

    struct ETHInterface_Header hdr = {
        .version = ETHInterface_CURRENT_VERSION,
        .zero = 0,
        .length_be = Endian_hostToBigEndian16(msg->length + ETHInterface_Header_SIZE),
        .fc00_be = Endian_hostToBigEndian16(0xfc00)
    };
    Message_push(msg, &hdr, ETHInterface_Header_SIZE, NULL);
    struct Except* eh = NULL;
    sendMessageInternal(msg, &addr, ctx, eh);
    return NULL;
}

static void handleEvent2(struct ETHInterface_pvt* context, struct Allocator* messageAlloc)
{
    struct Message* msg = Message_new(MAX_PACKET_SIZE, PADDING, messageAlloc);

    struct sockaddr_ll addr;
    uint32_t addrLen = sizeof(struct sockaddr_ll);

    // Knock it out of alignment by 2 bytes so that it will be
    // aligned when the idAndPadding is shifted off.
    Message_shift(msg, 2, NULL);

    int rc = recvfrom(context->socket,
                      msg->bytes,
                      msg->length,
                      0,
                      (struct sockaddr*) &addr,
                      &addrLen);

    if (rc < ETHInterface_Header_SIZE) {
        Log_debug(context->logger, "Failed to receive eth frame");
        return;
    }

    Assert_true(msg->length >= rc);
    msg->length = rc;

    //Assert_true(addrLen == SOCKADDR_LL_LEN);

    struct ETHInterface_Header hdr;
    Message_pop(msg, &hdr, ETHInterface_Header_SIZE, NULL);

    // here we could put a switch statement to handle different versions differently.
    if (hdr.version != ETHInterface_CURRENT_VERSION) {
        Log_debug(context->logger, "DROP unknown version");
        return;
    }

    uint16_t reportedLength = Endian_bigEndianToHost16(hdr.length_be);
    reportedLength -= ETHInterface_Header_SIZE;
    if (msg->length != reportedLength) {
        if (msg->length < reportedLength) {
            Log_debug(context->logger, "DROP size field is larger than frame");
            return;
        }
        msg->length = reportedLength;
    }
    if (hdr.fc00_be != Endian_hostToBigEndian16(0xfc00)) {
        Log_debug(context->logger, "DROP bad magic");
        return;
    }

    struct ETHInterface_Sockaddr  sockaddr = { .zero = 0 };
    Bits_memcpy(sockaddr.mac, addr.sll_addr, 6);
    sockaddr.generic.addrLen = ETHInterface_Sockaddr_SIZE;
    if (addr.sll_pkttype == PACKET_BROADCAST) {
        sockaddr.generic.flags |= Sockaddr_flags_BCAST;
    }

    Message_push(msg, &sockaddr, ETHInterface_Sockaddr_SIZE, NULL);

    Assert_true(!((uintptr_t)msg->bytes % 4) && "Alignment fault");

    Iface_send(&context->pub.generic.iface, msg);
}

static void handleEvent(void* vcontext)
{
    struct ETHInterface_pvt* context = Identity_check((struct ETHInterface_pvt*) vcontext);
    struct Allocator* messageAlloc = Allocator_child(context->pub.generic.alloc);
    handleEvent2(context, messageAlloc);
    Allocator_free(messageAlloc);
}

List* ETHInterface_listDevices(struct Allocator* alloc, struct Except* eh)
{
    List* out = List_new(alloc);
#ifndef android
    struct ifaddrs* ifaddr = NULL;
    if (getifaddrs(&ifaddr) || ifaddr == NULL) {
        Except_throw(eh, "getifaddrs() -> errno:%d [%s]", errno, strerror(errno));
    }
    for (struct ifaddrs* ifa = ifaddr; ifa; ifa = ifa->ifa_next) {
        if (ifa->ifa_addr && ifa->ifa_addr->sa_family == AF_PACKET) {
            List_addString(out, String_new(ifa->ifa_name, alloc), alloc);
        }
    }
    freeifaddrs(ifaddr);
#endif
    return out;
}

static int closeSocket(struct Allocator_OnFreeJob* j)
{
    struct ETHInterface_pvt* ctx = Identity_check((struct ETHInterface_pvt*) j->userData);
    close(ctx->socket);
    return 0;
}

struct ETHInterface* ETHInterface_new(struct EventBase* eventBase,
                                      const char* bindDevice,
                                      struct Allocator* alloc,
                                      struct Except* exHandler,
                                      struct Log* logger)
{
    struct ETHInterface_pvt* ctx = Allocator_calloc(alloc, sizeof(struct ETHInterface_pvt), 1);
    Identity_set(ctx);
    ctx->pub.generic.iface.send = sendMessage;
    ctx->pub.generic.alloc = alloc;
    ctx->logger = logger;

    struct ifreq ifr = { .ifr_ifindex = 0 };

    ctx->socket = socket(AF_PACKET, SOCK_DGRAM, Ethernet_TYPE_CJDNS);
    if (ctx->socket == -1) {
        Except_throw(exHandler, "call to socket() failed. [%s]", strerror(errno));
    }
    Allocator_onFree(alloc, closeSocket, ctx);

    CString_strncpy(ifr.ifr_name, bindDevice, IFNAMSIZ - 1);
    ctx->ifName = String_new(bindDevice, alloc);

    if (ioctl(ctx->socket, SIOCGIFINDEX, &ifr) == -1) {
        Except_throw(exHandler, "failed to find interface index [%s]", strerror(errno));
    }
    ctx->ifindex = ifr.ifr_ifindex;

    if (ioctl(ctx->socket, SIOCGIFFLAGS, &ifr) < 0) {
        Except_throw(exHandler, "ioctl(SIOCGIFFLAGS) [%s]", strerror(errno));
    }
    if (!((ifr.ifr_flags & IFF_UP) && (ifr.ifr_flags & IFF_RUNNING))) {
        Log_info(logger, "Bringing up interface [%s]", ifr.ifr_name);
        ifr.ifr_flags |= IFF_UP | IFF_RUNNING;
        if (ioctl(ctx->socket, SIOCSIFFLAGS, &ifr) < 0) {
            Except_throw(exHandler, "ioctl(SIOCSIFFLAGS) [%s]", strerror(errno));
        }
    }

    ctx->addrBase = (struct sockaddr_ll) {
        .sll_family = AF_PACKET,
        .sll_protocol = Ethernet_TYPE_CJDNS,
        .sll_ifindex = ctx->ifindex,
        .sll_hatype = ARPHRD_ETHER,
        .sll_pkttype = PACKET_OTHERHOST,
        .sll_halen = ETH_ALEN
    };

    if (bind(ctx->socket, (struct sockaddr*) &ctx->addrBase, sizeof(struct sockaddr_ll))) {
        Except_throw(exHandler, "call to bind() failed [%s]", strerror(errno));
    }

    Socket_makeNonBlocking(ctx->socket);

    Event_socketRead(handleEvent, ctx, ctx->socket, eventBase, alloc, exHandler);

    return &ctx->pub;
}
コード例 #25
0
ファイル: NDPServer.c プロジェクト: AdUser/cjdns
static int tryRouterSolicitation(struct Message* msg,
                                 struct Ethernet* eth,
                                 struct Headers_IP6Header* ip6,
                                 struct NDPServer_pvt* ns)
{
    if (msg->length < NDPHeader_RouterSolicitation_SIZE) {
        return 0;
    }
    struct NDPHeader_RouterSolicitation* sol = (struct NDPHeader_RouterSolicitation*)msg->bytes;

    if (sol->oneThirtyThree != 133 || sol->zero != 0) {
printf("wrong type/code for router solicitation\n");
        return 0;
    }

    if (ns->pub.prefixLen < 1 || ns->pub.prefixLen > 128) {
printf("address prefix not set\n");
        return 0;
    }

    if (Bits_memcmp(ip6->destinationAddr, UNICAST_ADDR, 16)
        && Bits_memcmp(ip6->destinationAddr, ALL_ROUTERS, 16))
    {
printf("wrong address for router solicitation\n");
        return 0;
    }

    // now we're committed.
    Message_shift(msg, -msg->length, NULL);

    // Prefix option
    struct NDPHeader_RouterAdvert_PrefixOpt prefix = {
        .three = 3,
        .four = 4,
        .bits = 0,
        .validLifetimeSeconds_be = 0xffffffffu,
        .preferredLifetimeSeconds_be = 0xffffffffu,
        .reservedTwo = 0
    };
    Bits_memcpyConst(prefix.prefix, ns->pub.advertisePrefix, 16);
    prefix.prefixLen = ns->pub.prefixLen;
    Message_push(msg, &prefix, sizeof(struct NDPHeader_RouterAdvert_PrefixOpt), NULL);

    // NDP message
    struct NDPHeader_RouterAdvert adv = {
        .oneThirtyFour = 134,
        .zero = 0,
        .checksum = 0,
        .currentHopLimit = 0,
        .bits = 0,
        .routerLifetime_be = Endian_hostToBigEndian16(10),
        .reachableTime_be = 0,
        .retransTime_be = 0
    };
    Message_push(msg, &adv, sizeof(struct NDPHeader_RouterAdvert), NULL);

    sendResponse(msg, eth, ip6, ns);
    return 1;
}

static int tryNeighborSolicitation(struct Message* msg,
                                   struct Ethernet* eth,
                                   struct Headers_IP6Header* ip6,
                                   struct NDPServer_pvt* ns)
{
    if (msg->length < NDPHeader_RouterSolicitation_SIZE) {
        return 0;
    }
    struct NDPHeader_NeighborSolicitation* sol = (struct NDPHeader_NeighborSolicitation*)msg->bytes;

    if (sol->oneThirtyFive != 135 || sol->zero != 0) {
printf("wrong type/code for neighbor solicitation\n");
        return 0;
    }

    if (Bits_memcmp(ip6->destinationAddr, UNICAST_ADDR, 16)
        && Bits_memcmp(ip6->destinationAddr, MULTICAST_ADDR, 13))
    {
printf("wrong address for neighbor solicitation\n");
        return 0;
    }

    // now we're committed.
    Message_shift(msg, -msg->length, NULL);

    struct NDPHeader_NeighborAdvert_MacOpt macOpt = {
        .two = 2,
        .one = 1
    };
    Bits_memcpyConst(macOpt.mac, eth->destAddr, 6);
    Message_push(msg, &macOpt, sizeof(struct NDPHeader_NeighborAdvert_MacOpt), NULL);

    struct NDPHeader_NeighborAdvert na = {
        .oneThirtySix = 136,
        .zero = 0,
        .checksum = 0,
        .bits = NDPHeader_NeighborAdvert_bits_ROUTER
            | NDPHeader_NeighborAdvert_bits_SOLICITED
            | NDPHeader_NeighborAdvert_bits_OVERRIDE
    };
    Bits_memcpyConst(na.targetAddr, UNICAST_ADDR, 16);
    Message_push(msg, &na, sizeof(struct NDPHeader_NeighborAdvert), NULL);

    sendResponse(msg, eth, ip6, ns);
    return 1;
}

static uint8_t receiveMessage(struct Message* msg, struct Interface* iface)
{
    struct NDPServer_pvt* ns = Identity_cast((struct NDPServer_pvt*)iface->receiverContext);

    if (msg->length < Ethernet_SIZE + Headers_IP6Header_SIZE) {
        return Interface_receiveMessage(&ns->pub.generic, msg);
    }

    struct Ethernet* eth = (struct Ethernet*) msg->bytes;
    struct Headers_IP6Header* ip6 = (struct Headers_IP6Header*) (&eth[1]);

    if (eth->ethertype != Ethernet_TYPE_IP6 || ip6->nextHeader != 58 /* ICMPv6 */) {
        return Interface_receiveMessage(&ns->pub.generic, msg);
    }

    // store the eth and ip6 headers so they don't get clobbered
    struct Ethernet storedEth;
    Message_pop(msg, &storedEth, sizeof(struct Ethernet), NULL);

    struct Headers_IP6Header storedIp6;
    Message_pop(msg, &storedIp6, sizeof(struct Headers_IP6Header), NULL);

    if (!tryNeighborSolicitation(msg, &storedEth, &storedIp6, ns)
        && !tryRouterSolicitation(msg, &storedEth, &storedIp6, ns))
    {
        Message_push(msg, &storedIp6, sizeof(struct Headers_IP6Header), NULL);
        Message_push(msg, &storedEth, sizeof(struct Ethernet), NULL);
        return Interface_receiveMessage(&ns->pub.generic, msg);
    }
    // responding happens in sendResponse..
    return 0;
}

static uint8_t sendMessage(struct Message* msg, struct Interface* iface)
{
    struct NDPServer_pvt* ns = Identity_cast((struct NDPServer_pvt*)iface);
    return Interface_sendMessage(ns->wrapped, msg);
}

struct NDPServer* NDPServer_new(struct Interface* external, struct Allocator* alloc)
{
    struct NDPServer_pvt* out = Allocator_calloc(alloc, sizeof(struct NDPServer_pvt), 1);
    out->wrapped = external;
    Identity_set(out);
    InterfaceWrapper_wrap(external, sendMessage, receiveMessage, &out->pub.generic);
    return &out->pub;
}
コード例 #26
0
ファイル: IpTunnel_test.c プロジェクト: DmytroOrlov/cjdns
static void testAddr(struct Context* ctx,
                     char* addr4, int prefix4, int alloc4,
                     char* addr6, int prefix6, int alloc6)
{
    struct Allocator* alloc = Allocator_child(ctx->alloc);
    struct IpTunnel* ipTun = IpTunnel_new(ctx->log, ctx->base, alloc, ctx->rand, NULL);

    struct Sockaddr* sa4 = NULL;
    struct Sockaddr_storage ip6ToGive;
    struct Sockaddr_storage ip4ToGive;
    if (addr4) {
        Assert_true(!Sockaddr_parse(addr4, &ip4ToGive));
        sa4 = &ip4ToGive.addr;
        Assert_true(Sockaddr_getFamily(sa4) == Sockaddr_AF_INET);
    }
    struct Sockaddr* sa6 = NULL;
    if (addr6) {
        Assert_true(!Sockaddr_parse(addr6, &ip6ToGive));
        sa6 = &ip6ToGive.addr;
        Assert_true(Sockaddr_getFamily(sa6) == Sockaddr_AF_INET6);
    }

    IpTunnel_allowConnection(ctx->pubKey,
                             sa6, prefix6, alloc6,
                             sa4, prefix4, alloc4,
                             ipTun);

    struct Message* msg = Message_new(64, 512, alloc);
    const char* requestForAddresses =
        "d"
          "1:q" "21:IpTunnel_getAddresses"
          "4:txid" "4:abcd"
        "e";
    CString_strcpy(msg->bytes, requestForAddresses);
    msg->length = CString_strlen(requestForAddresses);

    Message_push(msg, NULL, Headers_UDPHeader_SIZE, NULL);
    struct Headers_UDPHeader* uh = (struct Headers_UDPHeader*) msg->bytes;
    uh->length_be = Endian_hostToBigEndian16(msg->length - Headers_UDPHeader_SIZE);

    uint16_t* checksum = &((struct Headers_UDPHeader*) msg->bytes)->checksum_be;
    *checksum = 0;
    uint32_t length = msg->length;

    // Because of old reasons, we need to have at least an empty IPv6 header
    Message_push(msg, NULL, Headers_IP6Header_SIZE, NULL);
    struct Headers_IP6Header* ip = (struct Headers_IP6Header*) msg->bytes;
    Headers_setIpVersion(ip);
    ip->payloadLength_be = Endian_hostToBigEndian16(msg->length - Headers_IP6Header_SIZE);
    ip->nextHeader = 17;

    *checksum = Checksum_udpIp6(ip->sourceAddr, (uint8_t*) uh, length);

    pushRouteDataHeaders(ctx, msg);

    struct IfaceContext* nodeIf = Allocator_calloc(alloc, sizeof(struct IfaceContext), 1);
    nodeIf->ctx = ctx;
    nodeIf->iface.send = responseWithIpCallback;
    struct IfaceContext* tunIf = Allocator_calloc(alloc, sizeof(struct IfaceContext), 1);
    tunIf->ctx = ctx;
    tunIf->iface.send = messageToTun;
    Iface_plumb(&nodeIf->iface, &ipTun->nodeInterface);
    Iface_plumb(&tunIf->iface, &ipTun->tunInterface);
    ctx->expectedResponse =
        getExpectedResponse(sa4, prefix4, alloc4, sa6, prefix6, alloc6, alloc);
    Iface_send(&nodeIf->iface, msg);
    Assert_true(ctx->called == 2);
    ctx->called = 0;

    if (sa4) {
        uint8_t* addrBytes = NULL;
        Assert_true(Sockaddr_getAddress(sa4, &addrBytes) == 4);
        uint32_t addr;
        Bits_memcpy(&addr, addrBytes, 4);
        addr = Endian_bigEndianToHost32(addr);
        // Send from the address specified
        Assert_true(trySend4(alloc, addr, &nodeIf->iface, ctx));

        if (alloc4 < 32) {
            // Send from another (random) address in the prefix
            uint32_t flip = Random_uint32(ctx->rand) >> alloc4;
            if (prefix4 != 32) {
                Assert_true(trySend4(alloc, addr ^ flip, &nodeIf->iface, ctx));
            } else {
                // If netSize is not specified, we do not allow multi-address
                Assert_true(!trySend4(alloc, addr ^ flip, &nodeIf->iface, ctx));
            }
        } else {
コード例 #27
0
ファイル: SwitchPinger.c プロジェクト: krattai/cjdns
// incoming message from network, pointing to the beginning of the switch header.
static uint8_t receiveMessage(struct Message* msg, struct Interface* iface)
{
    struct SwitchPinger* ctx = Identity_check((struct SwitchPinger*) iface->receiverContext);
    struct SwitchHeader* switchHeader = (struct SwitchHeader*) msg->bytes;
    ctx->incomingLabel = Endian_bigEndianToHost64(switchHeader->label_be);
    ctx->incomingVersion = 0;
    Message_shift(msg, -SwitchHeader_SIZE, NULL);

    uint32_t handle = Message_pop32(msg, NULL);
    #ifdef Version_7_COMPAT
    if (handle != 0xffffffff) {
        Message_push32(msg, handle, NULL);
        handle = 0xffffffff;
        Assert_true(SwitchHeader_isV7Ctrl(switchHeader));
    }
    #endif
    Assert_true(handle == 0xffffffff);

    struct Control* ctrl = (struct Control*) msg->bytes;
    if (ctrl->type_be == Control_PONG_be) {
        Message_shift(msg, -Control_HEADER_SIZE, NULL);
        ctx->error = Error_NONE;
        if (msg->length >= Control_Pong_MIN_SIZE) {
            struct Control_Ping* pongHeader = (struct Control_Ping*) msg->bytes;
            ctx->incomingVersion = Endian_bigEndianToHost32(pongHeader->version_be);
            if (pongHeader->magic != Control_Pong_MAGIC) {
                Log_debug(ctx->logger, "dropped invalid switch pong");
                return Error_INVALID;
            }
            Message_shift(msg, -Control_Pong_HEADER_SIZE, NULL);
        } else {
            Log_debug(ctx->logger, "got runt pong message, length: [%d]", msg->length);
            return Error_INVALID;
        }

    } else if (ctrl->type_be == Control_KEYPONG_be) {
        Message_shift(msg, -Control_HEADER_SIZE, NULL);
        ctx->error = Error_NONE;
        if (msg->length >= Control_KeyPong_HEADER_SIZE && msg->length <= Control_KeyPong_MAX_SIZE) {
            struct Control_KeyPing* pongHeader = (struct Control_KeyPing*) msg->bytes;
            ctx->incomingVersion = Endian_bigEndianToHost32(pongHeader->version_be);
            if (pongHeader->magic != Control_KeyPong_MAGIC) {
                Log_debug(ctx->logger, "dropped invalid switch key-pong");
                return Error_INVALID;
            }
            Bits_memcpyConst(ctx->incomingKey, pongHeader->key, 32);
            Message_shift(msg, -Control_KeyPong_HEADER_SIZE, NULL);
        } else if (msg->length > Control_KeyPong_MAX_SIZE) {
            Log_debug(ctx->logger, "got overlong key-pong message, length: [%d]", msg->length);
            return Error_INVALID;
        } else {
            Log_debug(ctx->logger, "got runt key-pong message, length: [%d]", msg->length);
            return Error_INVALID;
        }

    } else if (ctrl->type_be == Control_ERROR_be) {
        Message_shift(msg, -Control_HEADER_SIZE, NULL);
        Assert_true((uint8_t*)&ctrl->content.error.errorType_be == msg->bytes);
        if (msg->length < (Control_Error_HEADER_SIZE + SwitchHeader_SIZE + Control_HEADER_SIZE)) {
            Log_debug(ctx->logger, "runt error packet");
            return Error_NONE;
        }

        ctx->error = Message_pop32(msg, NULL);
        Message_push32(msg, 0, NULL);

        Message_shift(msg, -(Control_Error_HEADER_SIZE + SwitchHeader_SIZE), NULL);

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

        Log_debug(ctx->logger, "error [%s] was caused by our [%s]",
                  Error_strerror(ctx->error),
                  Control_typeString(origCtrl->type_be));

        int shift;
        if (origCtrl->type_be == Control_PING_be) {
            shift = -(Control_HEADER_SIZE + Control_Ping_HEADER_SIZE);
        } else if (origCtrl->type_be == Control_KEYPING_be) {
            shift = -(Control_HEADER_SIZE + Control_KeyPing_HEADER_SIZE);
        } else {
            Assert_failure("problem in Ducttape.c");
        }
        if (msg->length < -shift) {
            Log_debug(ctx->logger, "runt error packet");
        }
        Message_shift(msg, shift, NULL);

    } else {
        // If it gets here then Ducttape.c is failing.
        Assert_true(false);
    }

    String* msgStr = &(String) { .bytes = (char*) msg->bytes, .len = msg->length };
    Pinger_pongReceived(msgStr, ctx->pinger);
    Bits_memset(ctx->incomingKey, 0, 32);
    return Error_NONE;
}

static void onPingResponse(String* data, uint32_t milliseconds, void* vping)
{
    struct Ping* p = Identity_check((struct Ping*) vping);
    enum SwitchPinger_Result err = SwitchPinger_Result_OK;
    uint64_t label = p->context->incomingLabel;
    if (data) {
        if (label != p->label) {
            err = SwitchPinger_Result_LABEL_MISMATCH;
        } else if ((p->data || data->len > 0) && !String_equals(data, p->data)) {
            err = SwitchPinger_Result_WRONG_DATA;
        } else if (p->context->error == Error_LOOP_ROUTE) {
            err = SwitchPinger_Result_LOOP_ROUTE;
        } else if (p->context->error) {
            err = SwitchPinger_Result_ERROR_RESPONSE;
        }
    } else {
        err = SwitchPinger_Result_TIMEOUT;
    }

    uint32_t version = p->context->incomingVersion;
    struct SwitchPinger_Response* resp =
        Allocator_calloc(p->pub.pingAlloc, sizeof(struct SwitchPinger_Response), 1);
    resp->version = p->context->incomingVersion;
    resp->res = err;
    resp->label = label;
    resp->data = data;
    resp->milliseconds = milliseconds;
    resp->version = version;
    Bits_memcpyConst(resp->key, p->context->incomingKey, 32);
    resp->ping = &p->pub;
    p->onResponse(resp, p->pub.onResponseContext);
}

static void sendPing(String* data, void* sendPingContext)
{
    struct Ping* p = Identity_check((struct Ping*) sendPingContext);

    struct Message* msg = Message_new(0, data->len + 512, p->pub.pingAlloc);

    while (((uintptr_t)msg->bytes - data->len) % 4) {
        Message_push8(msg, 0, NULL);
    }
    msg->length = 0;

    Message_push(msg, data->bytes, data->len, NULL);
    Assert_true(!((uintptr_t)msg->bytes % 4) && "alignment fault");

    if (p->pub.keyPing) {
        Message_shift(msg, Control_KeyPing_HEADER_SIZE, NULL);
        struct Control_KeyPing* keyPingHeader = (struct Control_KeyPing*) msg->bytes;
        keyPingHeader->magic = Control_KeyPing_MAGIC;
        keyPingHeader->version_be = Endian_hostToBigEndian32(Version_CURRENT_PROTOCOL);
        Bits_memcpyConst(keyPingHeader->key, p->context->myAddr->key, 32);
    } else {
        Message_shift(msg, Control_Ping_HEADER_SIZE, NULL);
        struct Control_Ping* pingHeader = (struct Control_Ping*) msg->bytes;
        pingHeader->magic = Control_Ping_MAGIC;
        pingHeader->version_be = Endian_hostToBigEndian32(Version_CURRENT_PROTOCOL);
    }

    Message_shift(msg, Control_HEADER_SIZE, NULL);
    struct Control* ctrl = (struct Control*) msg->bytes;
    ctrl->checksum_be = 0;
    ctrl->type_be = (p->pub.keyPing) ? Control_KEYPING_be : Control_PING_be;
    ctrl->checksum_be = Checksum_engine(msg->bytes, msg->length);

    #ifdef Version_7_COMPAT
        if (0) {
    #endif
    Message_push32(msg, 0xffffffff, NULL);
    #ifdef Version_7_COMPAT
        }
    #endif

    Message_shift(msg, SwitchHeader_SIZE, NULL);
    struct SwitchHeader* switchHeader = (struct SwitchHeader*) msg->bytes;
    switchHeader->label_be = Endian_hostToBigEndian64(p->label);

    SwitchHeader_setVersion(switchHeader, SwitchHeader_CURRENT_VERSION);
    SwitchHeader_setPenalty(switchHeader, 0);
    SwitchHeader_setCongestion(switchHeader, 0);

    #ifdef Version_7_COMPAT
        // v7 detects ctrl packets by the bit which has been
        // re-appropriated for suppression of errors.
        switchHeader->congestAndSuppressErrors = 1;
        SwitchHeader_setVersion(switchHeader, 0);
    #endif

    p->context->iface->sendMessage(msg, p->context->iface);
}

static String* RESULT_STRING_OK =             String_CONST_SO("pong");
static String* RESULT_STRING_LABEL_MISMATCH = String_CONST_SO("diff_label");
static String* RESULT_STRING_WRONG_DATA =     String_CONST_SO("diff_data");
static String* RESULT_STRING_ERROR_RESPONSE = String_CONST_SO("err_switch");
static String* RESULT_STRING_TIMEOUT =        String_CONST_SO("timeout");
static String* RESULT_STRING_UNKNOWN =        String_CONST_SO("err_unknown");
static String* RESULT_STRING_LOOP =           String_CONST_SO("err_loop");

String* SwitchPinger_resultString(enum SwitchPinger_Result result)
{
    switch (result) {
        case SwitchPinger_Result_OK:
            return RESULT_STRING_OK;

        case SwitchPinger_Result_LABEL_MISMATCH:
            return RESULT_STRING_LABEL_MISMATCH;

        case SwitchPinger_Result_WRONG_DATA:
            return RESULT_STRING_WRONG_DATA;

        case SwitchPinger_Result_ERROR_RESPONSE:
            return RESULT_STRING_ERROR_RESPONSE;

        case SwitchPinger_Result_TIMEOUT:
            return RESULT_STRING_TIMEOUT;

        case SwitchPinger_Result_LOOP_ROUTE:
            return RESULT_STRING_LOOP;

        default:
            return RESULT_STRING_UNKNOWN;
    };
}

static int onPingFree(struct Allocator_OnFreeJob* job)
{
    struct Ping* ping = Identity_check((struct Ping*)job->userData);
    struct SwitchPinger* ctx = Identity_check(ping->context);
    ctx->outstandingPings--;
    Assert_true(ctx->outstandingPings >= 0);
    return 0;
}

struct SwitchPinger_Ping* SwitchPinger_newPing(uint64_t label,
                                               String* data,
                                               uint32_t timeoutMilliseconds,
                                               SwitchPinger_ResponseCallback onResponse,
                                               struct Allocator* alloc,
                                               struct SwitchPinger* ctx)
{
    if (data && data->len > Control_Ping_MAX_SIZE) {
        return NULL;
    }

    if (ctx->outstandingPings > ctx->maxConcurrentPings) {
        Log_debug(ctx->logger, "Skipping switch ping because there are already [%d] outstanding",
                  ctx->outstandingPings);
        return NULL;
    }

    struct Pinger_Ping* pp =
        Pinger_newPing(data, onPingResponse, sendPing, timeoutMilliseconds, alloc, ctx->pinger);

    struct Ping* ping = Allocator_clone(pp->pingAlloc, (&(struct Ping) {
        .pub = {
            .pingAlloc = pp->pingAlloc
        },
        .label = label,
        .data = String_clone(data, pp->pingAlloc),
        .context = ctx,
        .onResponse = onResponse,
        .pingerPing = pp
    }));
コード例 #28
0
ファイル: Ducttape.c プロジェクト: wpapper/cjdns
static int handleOutgoing(struct DHTMessage* dmessage,
                          void* vcontext)
{
    struct Ducttape_pvt* context = Identity_cast((struct Ducttape_pvt*) vcontext);

    struct Message message = {
        .length = dmessage->length,
        .bytes = (uint8_t*) dmessage->bytes,
        .padding = 512,
        .capacity = DHTMessage_MAX_SIZE
    };

    Message_shift(&message, Headers_UDPHeader_SIZE);
    struct Headers_UDPHeader* uh = (struct Headers_UDPHeader*) message.bytes;
    uh->sourceAndDestPorts = 0;
    uh->length_be = Endian_hostToBigEndian16(dmessage->length);
    uh->checksum_be = 0;

    uint16_t payloadLength = message.length;

    Message_shift(&message, Headers_IP6Header_SIZE);
    struct Headers_IP6Header* header = (struct Headers_IP6Header*) message.bytes;
    header->versionClassAndFlowLabel = 0;
    header->flowLabelLow_be = 0;
    header->nextHeader = 17;
    header->hopLimit = 0;
    header->payloadLength_be = Endian_hostToBigEndian16(payloadLength);

    Bits_memcpyConst(header->sourceAddr,
                     context->myAddr.ip6.bytes,
                     Address_SEARCH_TARGET_SIZE);

    Bits_memcpyConst(header->destinationAddr,
                     dmessage->address->ip6.bytes,
                     Address_SEARCH_TARGET_SIZE);

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

    uh->checksum_be =
        Checksum_udpIp6(header->sourceAddr, (uint8_t*) uh, message.length - Headers_IP6Header_SIZE);

    struct Ducttape_MessageHeader* dtHeader = getDtHeader(&message, true);
    dtHeader->ip6Header = header;
    dtHeader->switchLabel = dmessage->address->path;

    struct SessionManager_Session* session =
        SessionManager_getSession(dmessage->address->ip6.bytes,
                                  dmessage->address->key,
                                  context->sm);
    if (session->version == Version_DEFAULT_ASSUMPTION && dmessage->replyTo) {
        int64_t* verPtr = Dict_getInt(dmessage->replyTo->asDict, String_CONST("p"));
        session->version = (verPtr) ? *verPtr : Version_DEFAULT_ASSUMPTION;
    }
    if (session->version == Version_DEFAULT_ASSUMPTION) {
        struct Node* n = RouterModule_getNode(dmessage->address->path, context->routerModule);
        if (n) {
            n->version = session->version =
                (n->version > session->version) ? n->version : session->version;
        }
    }

    sendToRouter(&message, dtHeader, session, context);

    return 0;
}

// Aligned on the beginning of the content.
static inline bool isRouterTraffic(struct Message* message, struct Headers_IP6Header* ip6)
{
    if (ip6->nextHeader != 17 || ip6->hopLimit != 0) {
        return false;
    }

    struct Headers_UDPHeader* uh = (struct Headers_UDPHeader*) message->bytes;
    return message->length >= Headers_UDPHeader_SIZE
        && uh->sourceAndDestPorts == 0
        && (int) Endian_bigEndianToHost16(uh->length_be) ==
            (message->length - Headers_UDPHeader_SIZE);
}

#define debugHandles(logger, session, message, ...) \
    do {                                                                               \
        uint8_t ip[40];                                                                \
        AddrTools_printIp(ip, session->ip6);                                           \
        Log_debug(logger, "ver[%u] send[%d] recv[%u] ip[%s] " message,                 \
                  session->version,                                                    \
                  Endian_hostToBigEndian32(session->sendHandle_be),                    \
                  Endian_hostToBigEndian32(session->receiveHandle_be),                 \
                  ip,                                                                  \
                  __VA_ARGS__);                                                        \
    } while (0)
//CHECKFILES_IGNORE expecting a ;

#define debugHandles0(logger, session, message) \
    debugHandles(logger, session, message "%s", "")

#define debugHandlesAndLabel(logger, session, label, message, ...) \
    do {                                                                               \
        uint8_t path[20];                                                              \
        AddrTools_printPath(path, label);                                              \
        debugHandles(logger, session, "path[%s] " message, path, __VA_ARGS__);         \
    } while (0)
//CHECKFILES_IGNORE expecting a ;

#define debugHandlesAndLabel0(logger, session, label, message) \
    debugHandlesAndLabel(logger, session, label, "%s", message)


/**
 * Message which is for us, message is aligned on the beginning of the content.
 * this is called from core() which calls through an interfaceMap.
 */
static inline uint8_t incomingForMe(struct Message* message,
                                    struct Ducttape_MessageHeader* dtHeader,
                                    struct SessionManager_Session* session,
                                    struct Ducttape_pvt* context,
                                    uint8_t herPublicKey[32])
{
    struct Address addr;
    Bits_memcpyConst(addr.ip6.bytes, session->ip6, 16);
    //AddressCalc_addressForPublicKey(addr.ip6.bytes, herPubKey);

    if (Bits_memcmp(addr.ip6.bytes, dtHeader->ip6Header->sourceAddr, 16)) {
        #ifdef Log_DEBUG
            uint8_t keyAddr[40];
            Address_printIp(keyAddr, &addr);
            Bits_memcpyConst(addr.ip6.bytes, dtHeader->ip6Header->sourceAddr, 16);
            uint8_t srcAddr[40];
            Address_printIp(srcAddr, &addr);
            Log_debug(context->logger,
                       "Dropped packet because source address is not same as key.\n"
                       "    %s source addr\n"
                       "    %s hash of key\n",
                       srcAddr,
                       keyAddr);
        #endif
        return Error_INVALID;
    }

    if (isRouterTraffic(message, dtHeader->ip6Header)) {
        // Check the checksum.
        struct Headers_UDPHeader* uh = (struct Headers_UDPHeader*) message->bytes;

        if (Checksum_udpIp6(dtHeader->ip6Header->sourceAddr, (uint8_t*)uh, message->length)) {
            #ifdef Log_DEBUG
                uint8_t keyAddr[40];
                Address_printIp(keyAddr, &addr);
                Log_debug(context->logger,
                          "Router packet with incorrect checksum, from [%s]", keyAddr);
            #endif
            return Error_INVALID;
        }

        // Shift off the UDP header.
        Message_shift(message, -Headers_UDPHeader_SIZE);
        addr.path = Endian_bigEndianToHost64(dtHeader->switchHeader->label_be);
        Bits_memcpyConst(addr.key, herPublicKey, 32);
        return incomingDHT(message, &addr, context);
    }

    if (!context->userIf) {
        Log_warn(context->logger,
                 "Dropping message because there is no router interface configured.\n");
        return Error_UNDELIVERABLE;
    }

    // prevent router advertizement schenanigans
    if (dtHeader->ip6Header->hopLimit == 255) {
        dtHeader->ip6Header->hopLimit--;
    }

    // Now write a message to the TUN device.
    // Need to move the ipv6 header forward up to the content because there's a crypto header
    // between the ipv6 header and the content which just got eaten.
    Message_shift(message, Headers_IP6Header_SIZE);
    uint16_t sizeDiff = message->bytes - (uint8_t*)dtHeader->ip6Header;
    if (sizeDiff) {
        dtHeader->ip6Header->payloadLength_be =
            Endian_hostToBigEndian16(
                Endian_bigEndianToHost16(dtHeader->ip6Header->payloadLength_be) - sizeDiff);
        Bits_memmoveConst(message->bytes, dtHeader->ip6Header, Headers_IP6Header_SIZE);
    }

    TUNMessageType_push(message, Ethernet_TYPE_IP6);

    context->userIf->sendMessage(message, context->userIf);
    return Error_NONE;
}

uint8_t Ducttape_injectIncomingForMe(struct Message* message,
                                     struct Ducttape* dt,
                                     uint8_t herPublicKey[32])
{
    struct Ducttape_pvt* context = Identity_cast((struct Ducttape_pvt*)dt);
    struct Ducttape_MessageHeader* dtHeader = getDtHeader(message, true);
    struct Headers_SwitchHeader sh;
    Bits_memcpyConst(&sh, message->bytes, Headers_SwitchHeader_SIZE);
    dtHeader->switchHeader = &sh;
    Message_shift(message, -Headers_SwitchHeader_SIZE);

    struct Headers_IP6Header ip6;
    Bits_memcpyConst(&ip6, message->bytes, Headers_IP6Header_SIZE);
    dtHeader->ip6Header = &ip6;
    Message_shift(message, -Headers_IP6Header_SIZE);

    struct SessionManager_Session s;
    AddressCalc_addressForPublicKey(s.ip6, herPublicKey);
    s.version = Version_CURRENT_PROTOCOL;

    return incomingForMe(message, dtHeader, &s, context, herPublicKey);
}

/**
 * Send a message to another switch.
 * Switchheader will precede the message.
 */
static inline uint8_t sendToSwitch(struct Message* message,
                                   struct Ducttape_MessageHeader* dtHeader,
                                   struct SessionManager_Session* session,
                                   struct Ducttape_pvt* context)
{
    uint64_t label = dtHeader->switchLabel;

    if (CryptoAuth_getState(&session->iface) >= CryptoAuth_HANDSHAKE3) {
        debugHandlesAndLabel0(context->logger, session, label, "layer2 sending run message");
        uint32_t sendHandle_be = session->sendHandle_be;
        #ifdef Version_2_COMPAT
        if (session->version < 3) {
            sendHandle_be |= HANDLE_FLAG_BIT_be;
        }
        #endif
        Message_push(message, &sendHandle_be, 4);
    } else {
        debugHandlesAndLabel0(context->logger, session, label, "layer2 sending start message");
        #ifdef Version_2_COMPAT
        if (session->version < 3) {
            Message_push(message, &session->receiveHandle_be, 4);
        }
        #endif
    }

    Message_shift(message, Headers_SwitchHeader_SIZE);

    Assert_true(message->bytes == (uint8_t*)dtHeader->switchHeader);

    return context->switchInterface.receiveMessage(message, &context->switchInterface);
}
コード例 #29
0
ファイル: Ducttape.c プロジェクト: wpapper/cjdns
// Called by the TUN device.
static inline uint8_t incomingFromTun(struct Message* message,
                                      struct Interface* iface)
{
    struct Ducttape_pvt* context = Identity_cast((struct Ducttape_pvt*) iface->receiverContext);

    uint16_t ethertype = TUNMessageType_pop(message);

    struct Headers_IP6Header* header = (struct Headers_IP6Header*) message->bytes;

    int version = Headers_getIpVersion(message->bytes);
    if ((ethertype == Ethernet_TYPE_IP4 && version != 4)
        || (ethertype == Ethernet_TYPE_IP6 && version != 6))
    {
        Log_warn(context->logger, "dropped packet because ip version [%d] "
                 "doesn't match ethertype [%u].", version, Endian_bigEndianToHost16(ethertype));
        return Error_INVALID;
    }

    if (ethertype != Ethernet_TYPE_IP6 || !AddressCalc_validAddress(header->sourceAddr)) {
        return context->ipTunnel->tunInterface.sendMessage(message,
                                                           &context->ipTunnel->tunInterface);
    }

    if (Bits_memcmp(header->sourceAddr, context->myAddr.ip6.bytes, 16)) {
        uint8_t expectedSource[40];
        AddrTools_printIp(expectedSource, context->myAddr.ip6.bytes);
        uint8_t packetSource[40];
        AddrTools_printIp(packetSource, header->sourceAddr);
        Log_warn(context->logger,
                 "dropped packet from [%s] because all messages must have source address [%s]",
                 (char*) packetSource, (char*) expectedSource);
        return Error_INVALID;
    }
    if (!Bits_memcmp(header->destinationAddr, context->myAddr.ip6.bytes, 16)) {
        // I'm Gonna Sit Right Down and Write Myself a Letter
        TUNMessageType_push(message, ethertype);
        iface->sendMessage(message, iface);
        return Error_NONE;
    }

    struct Ducttape_MessageHeader* dtHeader = getDtHeader(message, true);

    struct Node* bestNext = RouterModule_lookup(header->destinationAddr, context->routerModule);
    struct SessionManager_Session* nextHopSession;
    if (bestNext) {
        nextHopSession = SessionManager_getSession(bestNext->address.ip6.bytes,
                                                   bestNext->address.key,
                                                   context->sm);

        bestNext->version = nextHopSession->version = (bestNext->version > nextHopSession->version)
            ? bestNext->version : nextHopSession->version;

        dtHeader->switchLabel = bestNext->address.path;
        dtHeader->nextHopReceiveHandle = Endian_bigEndianToHost32(nextHopSession->receiveHandle_be);

        if (!Bits_memcmp(header->destinationAddr, bestNext->address.ip6.bytes, 16)) {
            // Direct send, skip the innermost layer of encryption.
            #ifdef Log_DEBUG
                uint8_t nhAddr[60];
                Address_print(nhAddr, &bestNext->address);
                Log_debug(context->logger, "Forwarding data to %s (last hop)\n", nhAddr);
            #endif
            return sendToRouter(message, dtHeader, nextHopSession, context);
        }
        // else { the message will need to be 3 layer encrypted but since we already did a lookup
        // of the best node to forward to, we can skip doing another lookup by storing a pointer
        // to that node in the context (bestNext).
    } else {
        #ifdef Log_WARN
            uint8_t thisAddr[40];
            uint8_t destAddr[40];
            AddrTools_printIp(thisAddr, context->myAddr.ip6.bytes);
            AddrTools_printIp(destAddr, header->destinationAddr);
            Log_warn(context->logger,
                     "Dropped message from TUN because this node [%s] is closest to dest [%s]",
                     thisAddr, destAddr);
        #endif
        return Error_UNDELIVERABLE;
    }

    #ifdef Log_DEBUG
        uint8_t destAddr[40];
        AddrTools_printIp(destAddr, header->destinationAddr);
        uint8_t nhAddr[60];
        Address_print(nhAddr, &bestNext->address);
        Log_debug(context->logger, "Sending to [%s] via [%s]", destAddr, nhAddr);
    #endif

    struct SessionManager_Session* session =
        SessionManager_getSession(header->destinationAddr, NULL, context->sm);

    // Copy the IP6 header back from where the CA header will be placed.
    // this is a mess.
    // We can't just copy the header to a safe place because the CryptoAuth
    // might buffer the message and send a connect-to-me packet and when the
    // hello packet comes in return, the CA will send the message and the header
    // needs to be in the message buffer.
    //
    // The CryptoAuth may send a 120 byte CA header and it might only send a 4 byte
    // nonce and 16 byte authenticator depending on its state.

    if (CryptoAuth_getState(&session->iface) < CryptoAuth_HANDSHAKE3) {
        // shift, copy, shift because shifting asserts that there is enough buffer space.
        Message_shift(message, Headers_CryptoAuth_SIZE + 4);
        Bits_memcpyConst(message->bytes, header, Headers_IP6Header_SIZE);
        Message_shift(message, -(Headers_IP6Header_SIZE + Headers_CryptoAuth_SIZE + 4));
        // now push the receive handle *under* the CA header.
        Message_push(message, &session->receiveHandle_be, 4);
        debugHandles0(context->logger, session, "layer3 sending start message");
    } else {
        // shift, copy, shift because shifting asserts that there is enough buffer space.
        Message_shift(message, 20);
        Bits_memmoveConst(message->bytes, header, Headers_IP6Header_SIZE);
        Message_shift(message, -(20 + Headers_IP6Header_SIZE));
        debugHandles0(context->logger, session, "layer3 sending run message");
    }

    // This comes out at outgoingFromCryptoAuth() then outgoingFromMe()
    dtHeader->receiveHandle = Endian_bigEndianToHost32(session->receiveHandle_be);
    dtHeader->layer = Ducttape_SessionLayer_INNER;
    return session->iface.sendMessage(message, &session->iface);
}
コード例 #30
0
static uint8_t sendMessage(struct Message* message, struct Interface* iface)
{
    struct PacketHeaderToUDPAddrInterface_pvt* context =
        Identity_check((struct PacketHeaderToUDPAddrInterface_pvt*) iface);

    struct Sockaddr_storage ss;
    Message_pop(message, &ss, context->pub.addr->addrLen, NULL);
    struct Sockaddr* addr = &ss.addr;

    struct Headers_UDPHeader udp;
    udp.srcPort_be = Endian_hostToBigEndian16(Sockaddr_getPort(context->pub.addr));
    udp.destPort_be = Endian_hostToBigEndian16(Sockaddr_getPort(addr));
    udp.length_be = Endian_hostToBigEndian16(message->length + Headers_UDPHeader_SIZE);
    udp.checksum_be = 0;
    Message_push(message, &udp, sizeof(struct Headers_UDPHeader), NULL);

    struct Headers_IP6Header ip = {
        .nextHeader = 17,
        .hopLimit = 255,
    };
    ip.payloadLength_be = Endian_hostToBigEndian16(message->length);
    Headers_setIpVersion(&ip);
    uint8_t* addrPtr = NULL;
    Assert_true(Sockaddr_getAddress(addr, &addrPtr) == 16);
    Bits_memcpyConst(ip.destinationAddr, addrPtr, 16);
    Assert_true(Sockaddr_getAddress(context->pub.addr, &addrPtr) == 16);
    Bits_memcpyConst(ip.sourceAddr, addrPtr, 16);

    uint16_t checksum = Checksum_udpIp6(ip.sourceAddr, message->bytes, message->length);
    ((struct Headers_UDPHeader*)message->bytes)->checksum_be = checksum;

    Message_push(message, &ip, sizeof(struct Headers_IP6Header), NULL);

    return Interface_sendMessage(context->wrapped, message);
}

static uint8_t receiveMessage(struct Message* message, struct Interface* iface)
{
    struct PacketHeaderToUDPAddrInterface_pvt* context =
        Identity_check((struct PacketHeaderToUDPAddrInterface_pvt*) iface->receiverContext);

    if (message->length < Headers_IP6Header_SIZE + Headers_UDPHeader_SIZE) {
        // runt
        return Error_NONE;
    }

    struct Headers_IP6Header* ip = (struct Headers_IP6Header*) message->bytes;

    // udp
    if (ip->nextHeader != 17) {
        return Error_NONE;
    }

    struct Allocator* alloc = Allocator_child(message->alloc);
    struct Sockaddr* addr = Sockaddr_clone(context->pub.addr, alloc);
    uint8_t* addrPtr = NULL;
    Assert_true(Sockaddr_getAddress(addr, &addrPtr) == 16);
    Bits_memcpyConst(addrPtr, ip->sourceAddr, 16);

    struct Headers_UDPHeader* udp = (struct Headers_UDPHeader*) (&ip[1]);
    Sockaddr_setPort(addr, Endian_bigEndianToHost16(udp->srcPort_be));

    if (Sockaddr_getPort(context->pub.addr) != Endian_bigEndianToHost16(udp->destPort_be)) {
        // not the right port
        return Error_NONE;
    }

    Message_shift(message, -(Headers_IP6Header_SIZE + Headers_UDPHeader_SIZE), NULL);
    Message_push(message, addr, addr->addrLen, NULL);

    return Interface_receiveMessage(&context->pub.generic, message);
}

struct AddrInterface* PacketHeaderToUDPAddrInterface_new(struct Interface* toWrap,
                                                         struct Allocator* alloc,
                                                         struct Sockaddr* addr)
{
    struct PacketHeaderToUDPAddrInterface_pvt* context =
        Allocator_malloc(alloc, sizeof(struct PacketHeaderToUDPAddrInterface_pvt));

    Bits_memcpyConst(context, (&(struct PacketHeaderToUDPAddrInterface_pvt) {
        .pub = {
            .generic = {
                .sendMessage = sendMessage,
                .senderContext = context,
                .allocator = alloc
            }
        },
        .wrapped = toWrap
    }), sizeof(struct PacketHeaderToUDPAddrInterface_pvt));