Exemplo n.º 1
0
int UDPInterface_beginConnection(const char* address,
                                 uint8_t cryptoKey[32],
                                 String* password,
                                 struct UDPInterface* udp)
{
    struct UDPInterface_pvt* udpif = (struct UDPInterface_pvt*) udp;
    struct Sockaddr_storage addr;
    if (Sockaddr_parse(address, &addr)) {
        return UDPInterface_beginConnection_BAD_ADDRESS;
    }
    if (addr.addr.addrLen != udp->addr->addrLen) {
        return UDPInterface_beginConnection_ADDRESS_MISMATCH;
    }

    struct Interface* iface = MultiInterface_ifaceForKey(udpif->multiIface, &addr);
    int ret = InterfaceController_registerPeer(udpif->ic, cryptoKey, password, false, false, iface);
    if (ret) {
        Allocator_free(iface->allocator);
        switch(ret) {
            case InterfaceController_registerPeer_BAD_KEY:
                return UDPInterface_beginConnection_BAD_KEY;

            case InterfaceController_registerPeer_OUT_OF_SPACE:
                return UDPInterface_beginConnection_OUT_OF_SPACE;

            default:
                return UDPInterface_beginConnection_UNKNOWN_ERROR;
        }
    }
    return 0;
}
Exemplo n.º 2
0
static int reconnectionNewEndpointTest(struct InterfaceController* ifController,
                                       uint8_t* pk,
                                       struct Message** fromSwitchPtr,
                                       struct Allocator* alloc,
                                       struct EventBase* eventBase,
                                       struct Log* logger,
                                       struct Interface* routerIf,
                                       struct Random* rand)
{
    struct Message* message;
    struct Interface iface = {
        .sendMessage = messageFromInterface,
        .senderContext = &message,
        .allocator = alloc
    };

    uint8_t* buffer = Allocator_malloc(alloc, 512);

    struct Message* outgoing =
        &(struct Message) { .length = 0, .padding = 512, .bytes = buffer + 512 };

    struct CryptoAuth* externalCa = CryptoAuth_new(alloc, NULL, eventBase, logger, rand);
    struct Interface* wrapped = CryptoAuth_wrapInterface(&iface, pk, NULL, false, "", externalCa);
    CryptoAuth_setAuth(String_CONST("passwd"), 1, wrapped);

    struct Interface icIface = {
        .allocator = alloc,
        .sendMessage = messageFromInterface,
        .senderContext = &message
    };

    InterfaceController_registerPeer(ifController, NULL, NULL, true, false, &icIface);

    uint8_t hexBuffer[1025];

    for (int i = 0; i < 4; i++) {

        outgoing->length = 0;
        outgoing->padding = 512;
        outgoing->bytes = buffer + 512;
        Message_shift(outgoing, 12, NULL);
        Bits_memcpyConst(outgoing->bytes, "hello world", 12);

        Message_shift(outgoing, SwitchHeader_SIZE, NULL);
        Bits_memcpyConst(outgoing->bytes, (&(struct SwitchHeader) {
            .label_be = Endian_hostToBigEndian64(1),
            .lowBits_be = 0
        }), SwitchHeader_SIZE);

        wrapped->sendMessage(outgoing, wrapped);

        *fromSwitchPtr = NULL;

        icIface.receiveMessage(outgoing, &icIface);

        message = *fromSwitchPtr;
        Assert_true(message);
        Assert_true(message->length == 24);

        Hex_encode(hexBuffer, 1025, message->bytes, message->length);
        printf("%s\n", hexBuffer);

        // Need to bounce the packets back when connecting after the first try.
        // This is needed to establish the CryptoAuth session and make the InterfaceController
        // merge the endpoints.
        if (i > 0) {
            // Reverse the bits to reverse the path:
            uint64_t path;
            Bits_memcpyConst(&path, message->bytes, 8);
            path = Bits_bitReverse64(path);
            Bits_memcpyConst(message->bytes, &path, 8);

            printf("sending back response.\n");
            routerIf->receiveMessage(message, routerIf);
            printf("forwarding response to external cryptoAuth.\n");
            iface.receiveMessage(message, &iface);
            printf("forwarded.\n");
        } else {
            printf("not responding because we don't want to establish a connection yet.\n");
        }
    }

    // check everything except the label
    Assert_true(!CString_strcmp((char*)hexBuffer+16, "0000000068656c6c6f20776f726c6400"));
    // check label: make sure the interface has been switched back into position 0.
    uint64_t label_be;
    Hex_decode((uint8_t*) &label_be, 8, hexBuffer, 16);
    uint64_t rev_label = Bits_bitReverse64(Endian_bigEndianToHost64(label_be));
    // check label is decoded to 0
    Assert_true(0 == NumberCompress_getDecompressed(rev_label,
                                                      NumberCompress_bitsUsedForLabel(rev_label)));
    // check no other bits are set
    uint64_t out = NumberCompress_getCompressed(0, NumberCompress_bitsUsedForLabel(rev_label));
    Assert_true(rev_label == out);
    return 0;
}
Exemplo n.º 3
0
static void handleBeacon(struct Message* msg, struct ETHInterface* context)
{
    if (!context->beaconState) {
        // accepting beacons disabled.
        Log_debug(context->logger, "Dropping beacon because beaconing is disabled");
        return;
    }

    struct sockaddr_ll addr;
    Bits_memcpyConst(&addr, &context->addrBase, sizeof(struct sockaddr_ll));
    Message_pop(msg, addr.sll_addr, 8);
    if (msg->length < Headers_Beacon_SIZE) {
        // Oversize messages are ok because beacons may contain more information in the future.
        Log_debug(context->logger, "Dropping wrong size beacon, expected [%d] got [%d]",
                  Headers_Beacon_SIZE, msg->length);
        return;
    }
    struct Headers_Beacon* beacon = (struct Headers_Beacon*) msg->bytes;

    uint32_t theirVersion = Endian_bigEndianToHost32(beacon->version_be);
    if (!Version_isCompatible(theirVersion, Version_CURRENT_PROTOCOL)) {
        #ifdef Log_DEBUG
            uint8_t mac[18];
            AddrTools_printMac(mac, addr.sll_addr);
            Log_debug(context->logger, "Dropped beacon from [%s] which was version [%d] "
                      "our version is [%d] making them incompatable",
                      mac, theirVersion, Version_CURRENT_PROTOCOL);
        #endif
        return;
    }

    #ifdef Log_DEBUG
        uint8_t mac[18];
        AddrTools_printMac(mac, addr.sll_addr);
        Log_debug(context->logger, "Got beacon from [%s]", mac);
    #endif

    String passStr = { .bytes = (char*) beacon->password, .len = Headers_Beacon_PASSWORD_LEN };
    struct Interface* iface = MultiInterface_ifaceForKey(context->multiIface, addr.sll_addr);
    int ret = InterfaceController_registerPeer(context->ic,
                                               beacon->publicKey,
                                               &passStr,
                                               false,
                                               true,
                                               iface);
    if (ret != 0) {
        uint8_t mac[18];
        AddrTools_printMac(mac, addr.sll_addr);
        Log_info(context->logger, "Got beacon from [%s] and registerPeer returned [%d]", mac, ret);
    }
}

static void sendBeacon(void* vcontext)
{
    struct ETHInterface* context = Identity_cast((struct ETHInterface*) vcontext);
    if (context->beaconState != ETHInterface_beacon_ACCEPTING_AND_SENDING) {
        // beaconing disabled
        return;
    }

    struct {
        struct sockaddr_ll addr;
        struct Headers_Beacon beacon;
    } content;

    Bits_memcpyConst(&content.addr, &context->addrBase, sizeof(struct sockaddr_ll));
    Bits_memset(content.addr.sll_addr, 0xff, 6);
    InterfaceController_populateBeacon(context->ic, &content.beacon);

    struct Message m = {
        .bytes=(uint8_t*)content.addr.sll_addr,
        .padding=0,
        .length=sizeof(struct Headers_Beacon) + 8
    };

    int ret;
    if ((ret = sendMessage(&m, &context->generic)) != 0) {
        Log_info(context->logger, "Got error [%d] sending beacon [%s]", ret, strerror(errno));
    }
}

static void handleEvent(void* vcontext)
{
    struct ETHInterface* context = Identity_cast((struct ETHInterface*) vcontext);

    struct Message message =
        { .bytes = context->messageBuff + PADDING, .padding = PADDING, .length = MAX_PACKET_SIZE };

    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(&message, 2);

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

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

    //Assert_true(addrLen == SOCKADDR_LL_LEN);

    // Pop the first 2 bytes of the message containing the node id and amount of padding.
    uint16_t idAndPadding_be;
    Message_pop(&message, &idAndPadding_be, 2);

    const uint16_t idAndPadding = Endian_bigEndianToHost16(idAndPadding_be);
    message.length = rc - 2 - ((idAndPadding & 7) * 8);
    const uint16_t id = idAndPadding >> 3;
    Message_push(&message, &id, 2);
    Message_push(&message, addr.sll_addr, 6);

    if (addr.sll_pkttype == PACKET_BROADCAST) {
        handleBeacon(&message, context);
        return;
    }

    /* 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, "Got ethernet frame from [%s]", buff);
    */

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

int ETHInterface_beginConnection(const char* macAddress,
                                 uint8_t cryptoKey[32],
                                 String* password,
                                 struct ETHInterface* ethIf)
{
    Identity_check(ethIf);
    struct sockaddr_ll addr;
    Bits_memcpyConst(&addr, &ethIf->addrBase, sizeof(struct sockaddr_ll));
    if (AddrTools_parseMac(addr.sll_addr, (const uint8_t*)macAddress)) {
        return ETHInterface_beginConnection_BAD_MAC;
    }

    struct Interface* iface = MultiInterface_ifaceForKey(ethIf->multiIface, &addr);
    int ret = InterfaceController_registerPeer(ethIf->ic, cryptoKey, password, false, false, iface);
    if (ret) {
        Allocator_free(iface->allocator);
        switch(ret) {
            case InterfaceController_registerPeer_BAD_KEY:
                return ETHInterface_beginConnection_BAD_KEY;

            case InterfaceController_registerPeer_OUT_OF_SPACE:
                return ETHInterface_beginConnection_OUT_OF_SPACE;

            default:
                return ETHInterface_beginConnection_UNKNOWN_ERROR;
        }
    }
    return 0;
}

int ETHInterface_beacon(struct ETHInterface* ethIf, int* state)
{
    Identity_check(ethIf);
    if (state) {
        ethIf->beaconState = *state;
        // Send out a beacon right away so we don't have to wait.
        if (ethIf->beaconState == ETHInterface_beacon_ACCEPTING_AND_SENDING) {
            sendBeacon(ethIf);
        }
    }
    return ethIf->beaconState;
}

struct ETHInterface* ETHInterface_new(struct EventBase* base,
                                      const char* bindDevice,
                                      struct Allocator* allocator,
                                      struct Except* exHandler,
                                      struct Log* logger,
                                      struct InterfaceController* ic)
{
    struct ETHInterface* context = Allocator_clone(allocator, (&(struct ETHInterface) {
        .generic = {
            .sendMessage = sendMessage,
            .allocator = allocator
        },
        .logger = logger,
        .ic = ic,
        .id = getpid()
    }));