Esempio n. 1
0
static Iface_DEFUN receiveMessage(struct Message* msg, struct Iface* external)
{
    struct TAPWrapper_pvt* tw = Identity_containerOf(external, struct TAPWrapper_pvt, external);

    if (msg->length < Ethernet_SIZE-2) {
        Log_debug(tw->log, "runt");
        return 0;
    }

    // wacky 14 byte headers, back off into outer-space to create the padding...
    Message_shift(msg, 2, NULL);

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

    // Not for us and not multicast...
    if (Bits_memcmp(eth.destAddr, TAPWrapper_LOCAL_MAC, Ethernet_ADDRLEN)
        && !(eth.destAddr[0] & 0x01))
    {
        if (Defined(Log_DEBUG)) {
            uint8_t printedMac[18];
            AddrTools_printMac(printedMac, eth.destAddr);
            Log_debug(tw->log, "Packet destine for unknown ethernet MAC [%s]", printedMac);
        }
        //return 0;
    }

    if (Bits_memcmp(eth.srcAddr, tw->pub.peerAddress, Ethernet_ADDRLEN)) {
        if (Bits_isZero(tw->pub.peerAddress, Ethernet_ADDRLEN)) {
            Bits_memcpy(tw->pub.peerAddress, eth.srcAddr, Ethernet_ADDRLEN);
        } else {
            #ifdef Log_DEBUG
                uint8_t printedMac[18];
                AddrTools_printMac(printedMac, eth.srcAddr);
                Log_debug(tw->log, "DROP Packet with unexpected source MAC [%s]", printedMac);
            #endif
            return 0;
        }
    }
    TUNMessageType_push(msg, eth.ethertype, NULL);
    return Iface_next(&tw->pub.internal, msg);
}
static void adminPeerStats(Dict* args, void* vcontext, String* txid, struct Allocator* alloc)
{
    struct Context* context = Identity_check((struct Context*)vcontext);
    struct InterfaceController_PeerStats* stats = NULL;

    int64_t* page = Dict_getIntC(args, "page");
    int i = (page) ? *page * ENTRIES_PER_PAGE : 0;

    int count = InterfaceController_getPeerStats(context->ic, alloc, &stats);

    List* list = List_new(alloc);
    for (int counter=0; i < count && counter++ < ENTRIES_PER_PAGE; i++) {
        Dict* d = Dict_new(alloc);
        Dict_putIntC(d, "bytesIn", stats[i].bytesIn, alloc);
        Dict_putIntC(d, "bytesOut", stats[i].bytesOut, alloc);

        Dict_putIntC(d, "recvKbps", stats[i].recvKbps, alloc);
        Dict_putIntC(d, "sendKbps", stats[i].sendKbps, alloc);

        Dict_putStringC(d, "addr", Address_toString(&stats[i].addr, alloc), alloc);

        String* lladdrString;
#ifdef HAS_ETH_INTERFACE
        if (ETHInterface_Sockaddr_SIZE == stats[i].lladdr->addrLen) {
            struct ETHInterface_Sockaddr* eth = (struct ETHInterface_Sockaddr*) stats[i].lladdr;
            uint8_t printedMac[18];
            AddrTools_printMac(printedMac, eth->mac);
            lladdrString = String_new(printedMac, alloc);
        } else {
            lladdrString = String_new(Sockaddr_print(stats[i].lladdr, alloc), alloc);
        }
#else
        lladdrString = String_new(Sockaddr_print(stats[i].lladdr, alloc), alloc);
#endif
        Dict_putStringC(d, "lladdr", lladdrString, alloc);

        String* stateString = String_new(InterfaceController_stateString(stats[i].state), alloc);
        Dict_putStringC(d, "state", stateString, alloc);

        Dict_putIntC(d, "last", stats[i].timeOfLastMessage, alloc);

        Dict_putIntC(d, "isIncoming", stats[i].isIncomingConnection, alloc);
        Dict_putIntC(d, "duplicates", stats[i].duplicates, alloc);
        Dict_putIntC(d, "lostPackets", stats[i].lostPackets, alloc);
        Dict_putIntC(d, "receivedOutOfRange", stats[i].receivedOutOfRange, alloc);

        Dict_putIntC(d, "ifNum", stats[i].ifNum, alloc);

        if (stats[i].user) {
            Dict_putStringC(d, "user", stats[i].user, alloc);
        }

        Dict_putIntC(d, "receivedPackets", stats[i].receivedPackets, alloc);

        List_addDict(list, d, alloc);
    }

    Dict* resp = Dict_new(alloc);
    Dict_putListC(resp, "peers", list, alloc);
    Dict_putIntC(resp, "total", count, alloc);

    if (i < count) {
        Dict_putIntC(resp, "more", 1, alloc);
    }

    Admin_sendMessage(resp, txid, context->admin);
}
Esempio 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()
    }));