Пример #1
0
static void showActiveSearch(Dict* args, void* vctx, String* txid, struct Allocator* alloc)
{
    struct Context* ctx = Identity_check((struct Context*) vctx);
    int number = *(Dict_getIntC(args, "number"));

    struct SearchRunner_SearchData* search =
        SearchRunner_showActiveSearch(ctx->runner, number, alloc);

    Dict* dict = Dict_new(alloc);

    // Nothing is an error
    Dict_putString(dict, String_new("error", alloc), String_new("none", alloc), alloc);

    if (number < search->activeSearches) {
        uint8_t target[40];
        AddrTools_printIp(target, search->target);
        Dict_putString(dict, String_new("target", alloc), String_new((char*)target, alloc), alloc);

        uint8_t lastNodeAsked[60];
        Address_print(lastNodeAsked, &search->lastNodeAsked);
        Dict_putString(dict,
                       String_new("lastNodeAsked", alloc),
                       String_new((char*)lastNodeAsked, alloc),
                       alloc);

        Dict_putInt(dict, String_new("totalRequests", alloc), search->totalRequests, alloc);
    }
    Dict_putInt(dict, String_new("activeSearches", alloc), search->activeSearches, alloc);

    Admin_sendMessage(dict, txid, ctx->admin);
}
Пример #2
0
int main()
{
    struct Allocator* alloc = MallocAllocator_new(1<<22);
    struct Random* rand = Random_new(alloc, NULL, NULL);

    uint8_t ip[16];
    uint8_t printedIp[40];
    uint8_t printedShortIp[40];
    uint8_t ipFromFull[16];
    uint8_t ipFromShort[16];

    for (int i = 0; i < 1024; ++i) {
        Random_bytes(rand, ip, 16);

        AddrTools_printIp(printedIp, ip);
        AddrTools_printShortIp(printedShortIp, ip);
        printf("%s\n%s\n\n", printedIp, printedShortIp);

        AddrTools_parseIp(ipFromFull, printedIp);
        AddrTools_parseIp(ipFromShort, printedShortIp);

        Assert_true(0 == Bits_memcmp(ip, ipFromFull, 16));
        Assert_true(0 == Bits_memcmp(ipFromFull, ipFromShort, 16));
    }

    return 0;
}
Пример #3
0
static void search(uint8_t target[16], struct Janitor* janitor)
{
    if (janitor->searches >= MAX_SEARCHES) {
        Log_debug(janitor->logger, "Skipping search because 20 are in progress");
        return;
    }
    #ifdef Log_DEBUG
        uint8_t targetStr[40];
        AddrTools_printIp(targetStr, target);
        Log_debug(janitor->logger, "Beginning search for [%s]", targetStr);
    #endif

    struct Allocator* searchAlloc = Allocator_child(janitor->allocator);
    struct RouterModule_Promise* rp =
        SearchRunner_search(target, janitor->searchRunner, searchAlloc);

    if (!rp) {
        Log_debug(janitor->logger, "SearchRunner_search() returned NULL, probably full.");
        Allocator_free(searchAlloc);
        return;
    }

    janitor->searches++;

    struct Janitor_Search* search = Allocator_clone(rp->alloc, (&(struct Janitor_Search) {
        .janitor = janitor,
        .alloc = searchAlloc,
    }));
Пример #4
0
int main()
{
    struct Allocator* alloc = MallocAllocator_new(1<<22);
    struct Random* rand = Random_new(alloc, NULL, NULL);
    struct Log* log = FileWriterLog_new(stdout, alloc);

    uint8_t ip[16];
    uint8_t printedIp[40];
    uint8_t printedShortIp[40];
    uint8_t ipFromFull[16];
    uint8_t ipFromShort[16];

    for (int i = 0; i < 1024; ++i) {
        Random_bytes(rand, ip, 16);

        for (int j = 0; j < 16; j++) {
            // make the random result have lots of zeros since that's what we're looking for.
            ip[j] = (ip[j] % 2) ? 0 : ip[j];
        }

        AddrTools_printIp(printedIp, ip);
        AddrTools_printShortIp(printedShortIp, ip);
        //printf("%s\n%s\n\n", printedIp, printedShortIp);

        AddrTools_parseIp(ipFromFull, printedIp);
        AddrTools_parseIp(ipFromShort, printedShortIp);

        Log_debug(log, "print/parse %s", printedIp);

        Assert_true(0 == Bits_memcmp(ip, ipFromFull, 16));
        Assert_true(0 == Bits_memcmp(ipFromFull, ipFromShort, 16));
    }
    Allocator_free(alloc);
    return 0;
}
Пример #5
0
int main(int argc, char** argv)
{
    if (argc < 2) {
        return usage(argv[0]);
    }

    uint8_t keyBytes[32];
    uint8_t ip6Bytes[16];
    String key = { .bytes = argv[1], .len = strlen(argv[1]) };

    int ret = Key_parse(&key, keyBytes, ip6Bytes);
    switch (ret) {
        case Key_parse_TOO_SHORT: fprintf(stderr, "ERROR: Key_parse_TOO_SHORT\n"); return 1;
        case Key_parse_MALFORMED: fprintf(stderr, "ERROR: Key_parse_MALFORMED\n"); return 1;
        case Key_parse_DECODE_FAILED: fprintf(stderr, "ERROR: Key_parse_DECODE_FAILED\n"); return 1;
        case Key_parse_INVALID: fprintf(stderr, "ERROR: Key_parse_INVALID\n"); return 1;
        case 0: break;
        default: fprintf(stderr, "ERROR: unknown error [%d]\n", ret); return 1;
    }

    uint8_t output[40] = {0};
    AddrTools_printIp(output, ip6Bytes);
    printf("%s\n", output);
    return 0;
}
Пример #6
0
static void getIp6(struct CryptoAuth_Session_pvt* session, uint8_t* addr)
{
    Assert_true(knowHerKey(session));
    uint8_t ip6[16];
    AddressCalc_addressForPublicKey(ip6, session->pub.herPublicKey);
    AddrTools_printIp(addr, ip6);
}
Пример #7
0
static void getIp6(struct CryptoAuth_Wrapper* wrapper, uint8_t* addr)
{
    if (knowHerKey(wrapper)) {
        uint8_t ip6[16];
        AddressCalc_addressForPublicKey(ip6, wrapper->herPerminentPubKey);
        AddrTools_printIp(addr, ip6);
    }
}
Пример #8
0
static void sessionStats(Dict* args,
                         void* vcontext,
                         String* txid,
                         struct Allocator* alloc)
{
    struct Context* context = Identity_check((struct Context*) vcontext);
    int64_t* handleP = Dict_getInt(args, String_CONST("handle"));
    uint32_t handle = *handleP;

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

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

    uint8_t printedAddr[40];
    AddrTools_printIp(printedAddr, session->caSession->herIp6);
    Dict_putString(r, String_CONST("ip6"), String_new(printedAddr, alloc), alloc);

    String* state =
        String_new(CryptoAuth_stateString(CryptoAuth_getState(session->caSession)), alloc);
    Dict_putString(r, String_CONST("state"), state, alloc);

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

    struct Address addr;
    Bits_memcpyConst(addr.key, session->caSession->herPublicKey, 32);
    addr.path = session->sendSwitchLabel;
    addr.protocolVersion = session->version;

    Dict_putString(r, String_CONST("addr"), Address_toString(&addr, alloc), alloc);

    Dict_putString(r, String_CONST("publicKey"),
                      Key_stringify(session->caSession->herPublicKey, alloc), alloc);
    Dict_putInt(r, String_CONST("version"), session->version, alloc);
    Dict_putInt(r, String_CONST("handle"), session->receiveHandle, alloc);
    Dict_putInt(r, String_CONST("sendHandle"), session->sendHandle, alloc);

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

    Dict_putString(r, String_CONST("deprecation"),
        String_CONST("publicKey,version will soon be removed"), alloc);

    Admin_sendMessage(r, txid, context->admin);
    return;
}
Пример #9
0
static void sessionStats(Dict* args,
                         void* vcontext,
                         String* txid,
                         struct Allocator* alloc)
{
    struct Context* context = vcontext;
    int64_t* handleP = Dict_getInt(args, String_CONST("handle"));
    uint32_t handle = *handleP;

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

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

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

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

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

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

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

    Admin_sendMessage(r, txid, context->admin);
    return;
}
Пример #10
0
static Iface_DEFUN searchReq(struct Message* msg, struct Pathfinder_pvt* pf)
{
    uint8_t addr[16];
    Message_pop(msg, addr, 16, NULL);
    Assert_true(!msg->length);
    uint8_t printedAddr[40];
    AddrTools_printIp(printedAddr, addr);
    Log_debug(pf->log, "Search req [%s]", printedAddr);

    struct Node_Two* node = NodeStore_nodeForAddr(pf->nodeStore, addr);
    if (node) {
        onBestPathChange(pf, node);
    } else {
        SearchRunner_search(addr, 20, 3, pf->searchRunner, pf->alloc);
    }
    return NULL;
}
Пример #11
0
/**
 * Send an arbitrary message to a node.
 *
 * @param message to be sent, must be prefixed with IpTunnel_PacketInfoHeader.
 * @param iface an interface for which receiverContext is the ducttape.
 */
static uint8_t sendToNode(struct Message* message, struct Interface* iface)
{
    struct Ducttape_pvt* context = Identity_cast((struct Ducttape_pvt*)iface->receiverContext);
    struct Ducttape_MessageHeader* dtHeader = getDtHeader(message, true);
    struct IpTunnel_PacketInfoHeader* header = (struct IpTunnel_PacketInfoHeader*) message->bytes;
    Message_shift(message, -IpTunnel_PacketInfoHeader_SIZE);
    struct Node* n = RouterModule_lookup(header->nodeIp6Addr, context->routerModule);
    if (n) {
        if (!Bits_memcmp(header->nodeKey, n->address.key, 32)) {
            // Found the node.
            #ifdef Log_DEBUG
                uint8_t nhAddr[60];
                Address_print(nhAddr, &n->address);
                Log_debug(context->logger, "Sending arbitrary data to [%s]", nhAddr);
            #endif

            struct SessionManager_Session* session =
                SessionManager_getSession(n->address.ip6.bytes, n->address.key, context->sm);

            n->version = session->version = (n->version > session->version)
                ? n->version : session->version;

            dtHeader->switchLabel = n->address.path;
            return sendToRouter(message, dtHeader, session, context);
        }
    }

    #ifdef Log_DEBUG
        uint8_t printedIp6[40];
        AddrTools_printIp(printedIp6, header->nodeIp6Addr);
        Log_debug(context->logger, "Couldn't find node [%s] for sending to.", printedIp6);
    #endif

    // Now lets trigger a search for this node.
    uint64_t now = Time_currentTimeMilliseconds(context->eventBase);
    if (context->timeOfLastSearch + context->timeBetweenSearches < now) {
        context->timeOfLastSearch = now;
        RouterModule_search(header->nodeIp6Addr, context->routerModule, context->alloc);
    }
    return 0;
}
Пример #12
0
int main(int argc, char** argv)
{
    struct Allocator* alloc = MallocAllocator_new(1<<22);
    struct Random* rand = Random_new(alloc, NULL, NULL);

    uint8_t privateKey[32];
    uint8_t publicKey[32];
    uint8_t ip[16];
    uint8_t hexPrivateKey[65];
    uint8_t printedIp[40];

    for (;;) {
        Random_bytes(rand, privateKey, 32);
        crypto_scalarmult_curve25519_base(publicKey, privateKey);
        if (AddressCalc_addressForPublicKey(ip, publicKey)) {
            Hex_encode(hexPrivateKey, 65, privateKey, 32);
            AddrTools_printIp(printedIp, ip);
            printf("%s %s\n", hexPrivateKey, printedIp);
        }
    }
    return 0;
}
Пример #13
0
static void dumpTable_addEntries(struct Context* ctx,
                                 int i,
                                 int j,
                                 struct List_Item* last,
                                 String* txid)
{
    uint8_t path[20];
    uint8_t ip[40];
    String* pathStr = &(String) { .len = 19, .bytes = (char*)path };
    String* ipStr = &(String) { .len = 39, .bytes = (char*)ip };
    Object* link = Int_OBJ(0xFFFFFFFF);
    Object* version = Int_OBJ(Version_DEFAULT_ASSUMPTION);
    Dict entry = Dict_CONST(
        String_CONST("ip"), String_OBJ(ipStr), Dict_CONST(
        String_CONST("link"), link, Dict_CONST(
        String_CONST("path"), String_OBJ(pathStr), Dict_CONST(
        String_CONST("version"), version, NULL
    ))));

    struct List_Item next = { .next = last, .elem = Dict_OBJ(&entry) };

    if (i >= ctx->store->size || j >= ENTRIES_PER_PAGE) {
        if (i > j) {
            dumpTable_send(ctx, last, (j >= ENTRIES_PER_PAGE), txid);
            return;
        }

        Address_printIp(ip, ctx->store->selfAddress);
        strcpy((char*)path, "0000.0000.0000.0001");
        version->as.number = Version_CURRENT_PROTOCOL;
        dumpTable_send(ctx, &next, (j >= ENTRIES_PER_PAGE), txid);
        return;
    }

    struct Node* n = NodeStore_dumpTable(ctx->store, i);
    link->as.number = n->reach;
    version->as.number = n->version;
    Address_printIp(ip, &n->address);
    AddrTools_printPath(path, n->address.path);

    dumpTable_addEntries(ctx, i + 1, j + 1, &next, txid);
}

static void dumpTable(Dict* args, void* vcontext, String* txid, struct Allocator* requestAlloc)
{
    struct Context* ctx = Identity_cast((struct Context*) vcontext);
    int64_t* page = Dict_getInt(args, String_CONST("page"));
    int i = (page) ? *page * ENTRIES_PER_PAGE : 0;
    dumpTable_addEntries(ctx, i, 0, NULL, txid);
}

static bool isOneHop(struct Node_Link* link)
{
    struct EncodingScheme* ps = link->parent->encodingScheme;
    int num = EncodingScheme_getFormNum(ps, link->cannonicalLabel);
    Assert_always(num > -1 && num < ps->count);
    return EncodingScheme_formSize(&ps->forms[num]) == Bits_log2x64(link->cannonicalLabel);
}

static void getLink(Dict* args, void* vcontext, String* txid, struct Allocator* alloc)
{
    struct Context* ctx = Identity_cast((struct Context*) vcontext);

    Dict* ret = Dict_new(alloc);
    Dict* result = Dict_new(alloc);
    Dict_putDict(ret, String_new("result", alloc), result, alloc);
    Dict_putString(ret, String_new("error", alloc), String_new("none", alloc), alloc);

    struct Node_Link* link;

    String* ipStr = Dict_getString(args, String_new("parent", alloc));
    int64_t* linkNum = Dict_getInt(args, String_new("linkNum", alloc));
    uint8_t ip[16];
    if (ipStr->len != 39 || AddrTools_parseIp(ip, ipStr->bytes)) {
        Dict_remove(ret, String_CONST("result"));
        Dict_putString(ret,
                       String_new("error", alloc),
                       String_new("Could not parse ip", alloc),
                       alloc);

    } else if ((link = NodeStore_getLink(ctx->store, ip, *linkNum))) {
        Dict_putInt(result,
                    String_new("inverseLinkEncodingFormNumber", alloc),
                    link->inverseLinkEncodingFormNumber,
                    alloc);
        Dict_putInt(result, String_new("linkState", alloc), link->linkState, alloc);

        Dict_putInt(result, String_new("isOneHop", alloc), isOneHop(link), alloc);

        String* cannonicalLabel = String_newBinary(NULL, 19, alloc);
        AddrTools_printPath(cannonicalLabel->bytes, link->cannonicalLabel);
        Dict_putString(result, String_new("cannonicalLabel", alloc), cannonicalLabel, alloc);

        String* parent = String_newBinary(NULL, 39, alloc);
        AddrTools_printIp(parent->bytes, link->parent->address.ip6.bytes);
        Dict_putString(result, String_new("parent", alloc), parent, alloc);

        String* child = String_newBinary(NULL, 39, alloc);
        AddrTools_printIp(child->bytes, link->child->address.ip6.bytes);
        Dict_putString(result, String_new("child", alloc), child, alloc);
    }

    Admin_sendMessage(ret, txid, ctx->admin);
}
static void getNode(Dict* args, void* vcontext, String* txid, struct Allocator* alloc)
{
    struct Context* ctx = Identity_cast((struct Context*) vcontext);

    Dict* ret = Dict_new(alloc);
    Dict* result = Dict_new(alloc);
    Dict_putDict(ret, String_new("result", alloc), result, alloc);
    Dict_putString(ret, String_new("error", alloc), String_new("none", alloc), alloc);

    // no ipStr specified --> return self-node
    struct Node_Two* node = ctx->store->selfNode;

    String* ipStr = Dict_getString(args, String_new("ip", alloc));
    uint8_t ip[16];
    while (ipStr) {
        if (ipStr->len != 39 || AddrTools_parseIp(ip, ipStr->bytes)) {
            Dict_remove(ret, String_CONST("result"));
            Dict_putString(ret,
                           String_new("error", alloc),
                           String_new("Could not parse ip", alloc),
                           alloc);

        } else if (!(node = NodeStore_getNode2(ctx->store, ip))) {
            // not found
        } else {
            break;
        }

        Admin_sendMessage(ret, txid, ctx->admin);
        return;
    }

    Dict_putInt(result, String_new("protocolVersion", alloc), node->version, alloc);

    String* key = Key_stringify(node->address.key, alloc);
    Dict_putString(result, String_new("key", alloc), key, alloc);

    uint32_t linkCount = NodeStore_linkCount(node);
    Dict_putInt(result, String_new("linkCount", alloc), linkCount, alloc);

    List* encScheme = EncodingScheme_asList(node->encodingScheme, alloc);
    Dict_putList(result, String_new("encodingScheme", alloc), encScheme, alloc);

    Admin_sendMessage(ret, txid, ctx->admin);
}

static void getRouteLabel(Dict* args, void* vcontext, String* txid, struct Allocator* requestAlloc)
{
    struct Context* ctx = Identity_cast((struct Context*) vcontext);

    char* err = NULL;

    String* pathToParentS = Dict_getString(args, String_CONST("pathToParent"));
    uint64_t pathToParent;
    if (pathToParentS->len != 19) {
        err = "pathToParent incorrect length";
    } else if (AddrTools_parsePath(&pathToParent, pathToParentS->bytes)) {
        err = "Failed to parse pathToParent";
    }

    String* childAddressS = Dict_getString(args, String_CONST("childAddress"));
    uint8_t childAddress[16];
    if (childAddressS->len != 39) {
        err = "childAddress of incorrect length, must be a 39 character full ipv6 address";
    } else if (AddrTools_parseIp(childAddress, childAddressS->bytes)) {
        err = "Failed to parse childAddress";
    }

    uint64_t label = UINT64_MAX;
    if (!err) {
        label = NodeStore_getRouteLabel(ctx->store, pathToParent, childAddress);
        err = NodeStore_getRouteLabel_strerror(label);
    }
    Dict* response = Dict_new(requestAlloc);
    if (!err) {
        String* printedPath = String_newBinary(NULL, 19, requestAlloc);
        AddrTools_printPath(printedPath->bytes, label);
        Dict_putString(response, String_new("result", requestAlloc), printedPath, requestAlloc);
        Dict_putString(response,
                       String_new("error", requestAlloc),
                       String_new("none", requestAlloc),
                       requestAlloc);
        Admin_sendMessage(response, txid, ctx->admin);
    } else {
        Dict_putString(response,
                       String_new("error", requestAlloc),
                       String_new(err, requestAlloc),
                       requestAlloc);
        Admin_sendMessage(response, txid, ctx->admin);
    }
}

void NodeStore_admin_register(struct NodeStore* nodeStore,
                              struct Admin* admin,
                              struct Allocator* alloc)
{
    struct Context* ctx = Allocator_clone(alloc, (&(struct Context) {
        .admin = admin,
        .alloc = alloc,
        .store = nodeStore
    }));
    Identity_set(ctx);

    Admin_registerFunction("NodeStore_dumpTable", dumpTable, ctx, false,
        ((struct Admin_FunctionArg[]) {
            { .name = "page", .required = 1, .type = "Int" },
        }), admin);

    Admin_registerFunction("NodeStore_getLink", getLink, ctx, true,
        ((struct Admin_FunctionArg[]) {
            { .name = "parent", .required = 1, .type = "String" },
            { .name = "linkNum", .required = 1, .type = "Int" },
        }), admin);
Пример #14
0
static Iface_DEFUN incomingFromTunIf(struct Message* msg, struct Iface* tunIf)
{
    struct TUNAdapter_pvt* ud = Identity_containerOf(tunIf, struct TUNAdapter_pvt, pub.tunIf);

    uint16_t ethertype = TUNMessageType_pop(msg, NULL);

    int version = Headers_getIpVersion(msg->bytes);
    if ((ethertype == Ethernet_TYPE_IP4 && version != 4)
        || (ethertype == Ethernet_TYPE_IP6 && version != 6))
    {
        Log_debug(ud->log, "DROP packet because ip version [%d] "
                  "doesn't match ethertype [%u].", version, Endian_bigEndianToHost16(ethertype));
        return NULL;
    }

    if (ethertype == Ethernet_TYPE_IP4) {
        return Iface_next(&ud->pub.ipTunnelIf, msg);
    }
    if (ethertype != Ethernet_TYPE_IP6) {
        Log_debug(ud->log, "DROP packet unknown ethertype [%u]",
                  Endian_bigEndianToHost16(ethertype));
        return NULL;
    }

    if (msg->length < Headers_IP6Header_SIZE) {
        Log_debug(ud->log, "DROP runt");
        return NULL;
    }

    struct Headers_IP6Header* header = (struct Headers_IP6Header*) msg->bytes;
    if (!AddressCalc_validAddress(header->destinationAddr)) {
        return Iface_next(&ud->pub.ipTunnelIf, msg);
    }
    if (Bits_memcmp(header->sourceAddr, ud->myIp6, 16)) {
        if (Defined(Log_DEBUG)) {
            uint8_t expectedSource[40];
            AddrTools_printIp(expectedSource, ud->myIp6);
            uint8_t packetSource[40];
            AddrTools_printIp(packetSource, header->sourceAddr);
            Log_debug(ud->log,
                      "DROP packet from [%s] because all messages must have source address [%s]",
                      packetSource, expectedSource);
        }
        return NULL;
    }
    if (!Bits_memcmp(header->destinationAddr, ud->myIp6, 16)) {
        // I'm Gonna Sit Right Down and Write Myself a Letter
        TUNMessageType_push(msg, ethertype, NULL);
        return Iface_next(tunIf, msg);
    }
    if (!Bits_memcmp(header->destinationAddr, "\xfc\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01", 16)) {
        return Iface_next(&ud->pub.magicIf, msg);
    }

    // first move the dest addr to the right place.
    Bits_memmoveConst(&header->destinationAddr[-DataHeader_SIZE], header->destinationAddr, 16);

    Message_shift(msg, DataHeader_SIZE + RouteHeader_SIZE - Headers_IP6Header_SIZE, NULL);
    struct RouteHeader* rh = (struct RouteHeader*) msg->bytes;

    struct DataHeader* dh = (struct DataHeader*) &rh[1];
    Bits_memset(dh, 0, DataHeader_SIZE);
    DataHeader_setContentType(dh, header->nextHeader);
    DataHeader_setVersion(dh, DataHeader_CURRENT_VERSION);

    // Other than the ipv6 addr at the end, everything is zeros right down the line.
    Bits_memset(rh, 0, RouteHeader_SIZE - 16);

    return Iface_next(&ud->pub.upperDistributorIf, msg);
}
Пример #15
0
/**
 * Messages with content encrypted and header decrypted are sent here to be forwarded.
 * they may come from us, or from another node and may be to us or to any other node.
 * Message is aligned on the beginning of the ipv6 header.
 */
static inline int core(struct Message* message,
                       struct Ducttape_MessageHeader* dtHeader,
                       struct SessionManager_Session* session,
                       struct Ducttape_pvt* context)
{
    struct Headers_IP6Header* ip6Header = (struct Headers_IP6Header*) message->bytes;
    dtHeader->ip6Header = ip6Header;

    if (isForMe(message, context)) {
        Message_shift(message, -Headers_IP6Header_SIZE);

        if (Bits_memcmp(session->ip6, ip6Header->sourceAddr, 16)) {
            // triple encrypted
            // This call goes to incomingForMe()
            struct SessionManager_Session* session =
                SessionManager_getSession(ip6Header->sourceAddr, NULL, context->sm);

            #ifdef Log_DEBUG
                uint8_t addr[40];
                AddrTools_printIp(addr, ip6Header->sourceAddr);
                Log_debug(context->logger, "Incoming layer3 message, ostensibly from [%s]", addr);
            #endif

            dtHeader->receiveHandle = Endian_bigEndianToHost32(session->receiveHandle_be);
            dtHeader->layer = Ducttape_SessionLayer_INNER;
            return session->iface.receiveMessage(message, &session->iface);
        } else {
            // double encrypted, inner layer plaintext.
            // The session is still set from the router-to-router traffic and that is the one we use
            // to determine the node's id.
            return incomingForMe(message, dtHeader, session, context,
                                 CryptoAuth_getHerPublicKey(&session->iface));
        }
    }

    if (ip6Header->hopLimit == 0) {
        Log_debug(context->logger, "dropped message because hop limit has been exceeded.\n");
        // TODO: send back an error message in response.
        return Error_UNDELIVERABLE;
    }
    ip6Header->hopLimit--;

    struct SessionManager_Session* nextHopSession = NULL;
    if (!dtHeader->nextHopReceiveHandle || !dtHeader->switchLabel) {
        struct Node* n = RouterModule_lookup(ip6Header->destinationAddr, context->routerModule);
        if (n) {
            nextHopSession =
                SessionManager_getSession(n->address.ip6.bytes, n->address.key, context->sm);
            dtHeader->switchLabel = n->address.path;
        }
    } else {
        nextHopSession =
            SessionManager_sessionForHandle(dtHeader->nextHopReceiveHandle, context->sm);
    }

    if (nextHopSession) {
        #ifdef Log_DEBUG
            struct Address addr;
            Bits_memcpyConst(addr.ip6.bytes, nextHopSession->ip6, 16);
            addr.path = dtHeader->switchLabel;
            uint8_t nhAddr[60];
            Address_print(nhAddr, &addr);
            if (Bits_memcmp(ip6Header->destinationAddr, addr.ip6.bytes, 16)) {
                // Potentially forwarding for ourselves.
                struct Address destination;
                Bits_memcpyConst(destination.ip6.bytes, ip6Header->destinationAddr, 16);
                uint8_t ipAddr[40];
                Address_printIp(ipAddr, &destination);
                Log_debug(context->logger, "Forwarding data to %s via %s\n", ipAddr, nhAddr);
            } else {
                // Definitely forwarding on behalf of someone else.
                Log_debug(context->logger, "Forwarding data to %s (last hop)\n", nhAddr);
            }
        #endif
        return sendToRouter(message, dtHeader, nextHopSession, context);
    }

    #ifdef Log_INFO
        struct Address destination;
        Bits_memcpyConst(destination.ip6.bytes, ip6Header->destinationAddr, 16);
        uint8_t ipAddr[40];
        Address_printIp(ipAddr, &destination);
        Log_info(context->logger, "Dropped message because this node is the closest known "
                                   "node to the destination %s.", ipAddr);
    #endif
    return Error_UNDELIVERABLE;
}
Пример #16
0
static void nodeForAddr(Dict* args, void* vcontext, String* txid, struct Allocator* alloc)
{
    struct Context* ctx = Identity_check((struct Context*) vcontext);

    Dict* ret = Dict_new(alloc);
    Dict* result = Dict_new(alloc);
    Dict_putDict(ret, String_new("result", alloc), result, alloc);
    Dict_putString(ret, String_new("error", alloc), String_new("none", alloc), alloc);

    // no ipStr specified --> return self-node
    struct Node_Two* node = ctx->store->selfNode;

    String* ipStr = Dict_getString(args, String_new("ip", alloc));
    uint8_t ip[16];
    while (ipStr) {
        if (AddrTools_parseIp(ip, ipStr->bytes)) {
            Dict_remove(ret, String_CONST("result"));
            Dict_putString(ret,
                           String_new("error", alloc),
                           String_new("parse_ip", alloc),
                           alloc);

        } else if (!(node = NodeStore_nodeForAddr(ctx->store, ip))) {
            // not found
        } else {
            break;
        }

        Admin_sendMessage(ret, txid, ctx->admin);
        return;
    }

    Dict_putInt(result, String_new("protocolVersion", alloc), node->address.protocolVersion, alloc);

    String* key = Key_stringify(node->address.key, alloc);
    Dict_putString(result, String_new("key", alloc), key, alloc);

    uint32_t count = linkCount(node);
    Dict_putInt(result, String_new("linkCount", alloc), count, alloc);

    Dict_putInt(result, String_new("cost", alloc), Node_getCost(node), alloc);

    List* encScheme = EncodingScheme_asList(node->encodingScheme, alloc);
    Dict_putList(result, String_new("encodingScheme", alloc), encScheme, alloc);

    Dict* bestParent = Dict_new(alloc);
    String* parentIp = String_newBinary(NULL, 39, alloc);
    AddrTools_printIp(parentIp->bytes, Node_getBestParent(node)->parent->address.ip6.bytes);
    Dict_putString(bestParent, String_CONST("ip"), parentIp, alloc);

    String* parentChildLabel = String_newBinary(NULL, 19, alloc);
    AddrTools_printPath(parentChildLabel->bytes, Node_getBestParent(node)->cannonicalLabel);
    Dict_putString(bestParent, String_CONST("parentChildLabel"), parentChildLabel, alloc);

    int isOneHop = Node_isOneHopLink(Node_getBestParent(node));
    Dict_putInt(bestParent, String_CONST("isOneHop"), isOneHop, alloc);

    Dict_putDict(result, String_CONST("bestParent"), bestParent, alloc);

    String* bestLabel = String_newBinary(NULL, 19, alloc);
    AddrTools_printPath(bestLabel->bytes, node->address.path);
    Dict_putString(result, String_CONST("routeLabel"), bestLabel, alloc);

    Admin_sendMessage(ret, txid, ctx->admin);
}
Пример #17
0
// 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);
}
Пример #18
0
static void addIp6Address(const char* interfaceName,
                          const uint8_t address[16],
                          int prefixLen,
                          struct Log* logger,
                          struct Except* eh)
{
    /* stringify our IP address */
    char myIp[40];
    AddrTools_printIp((uint8_t*)myIp, address);

    /* set up the interface ip assignment request */
    struct in6_aliasreq in6_addreq;
    memset(&in6_addreq, 0, sizeof(in6_addreq));
    in6_addreq.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME;
    in6_addreq.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME;

    /* parse the IPv6 address and add it to the request */
    struct addrinfo hints, *result;

    bzero(&hints, sizeof(struct addrinfo));
    hints.ai_family = AF_INET6;
    int err = getaddrinfo((const char *)myIp, NULL, &hints, &result);
    if (err) {
        // Should never happen since the address is specified as binary.
        Except_throw(eh, "bad IPv6 address [%s]", gai_strerror(err));
    }

    memcpy(&in6_addreq.ifra_addr, result->ai_addr, result->ai_addrlen);

    /* turn the prefixlen into a mask, and add it to the request */
    struct sockaddr_in6* mask = &in6_addreq.ifra_prefixmask;
    u_char *cp;

    int len = prefixLen;
    mask->sin6_len = sizeof(*mask);
    if ((prefixLen == 0) || (prefixLen == 128)) {
        memset(&mask->sin6_addr, 0xff, sizeof(struct in6_addr));
    } else {
        memset((void *)&mask->sin6_addr, 0x00, sizeof(mask->sin6_addr));
        for (cp = (u_char *)&mask->sin6_addr; len > 7; len -= 8) {
            *cp++ = 0xff;
        }
        *cp = 0xff << (8 - len);
    }

    strncpy(in6_addreq.ifra_name, interfaceName, sizeof(in6_addreq.ifra_name));

    /* do the actual assignment ioctl */
    int s = socket(AF_INET6, SOCK_DGRAM, 0);
    if (s < 0) {
        Except_throw(eh, "socket() [%s]", strerror(errno));
    }

    if (ioctl(s, SIOCAIFADDR_IN6, &in6_addreq) < 0) {
        int err = errno;
        close(s);
        Except_throw(eh, "ioctl(SIOCAIFADDR) [%s]", strerror(err));
    }

    Log_info(logger, "Configured IPv6 [%s/%i] for [%s]", myIp, prefixLen, interfaceName);

    close(s);
}
Пример #19
0
static struct Address* createAddress(int mostSignificantAddressSpaceByte, int* hops)
{
    uint64_t path = getPath(hops);
    struct Address address = { .path = 0 };

    if (!genKeys) {
        if ((int)(sizeof(KEYS) / sizeof(*KEYS)) < (nextKey + 1)) {
            missingKey();
        }
        Bits_memcpyConst(address.key, KEYS[nextKey], 32);
        if (AddressCalc_addressForPublicKey(address.ip6.bytes, address.key)
            && (mostSignificantAddressSpaceByte == -1
                || address.ip6.bytes[8] == mostSignificantAddressSpaceByte))
        {
            nextKey++;
            uint8_t publicKeyHex[65];
            Hex_encode(publicKeyHex, 65, address.key, 32);
            printf("created new key: [%s]\n", publicKeyHex);

            address.path = path;
            return Allocator_clone(alloc, &address);
        } else {
            uint8_t publicKeyHex[65];
            Hex_encode(publicKeyHex, 65, address.key, 32);
            printf("bad key: [%s]\n", publicKeyHex);
            if (address.ip6.ints.three) {
                uint8_t printedAddr[40];
                AddrTools_printIp(printedAddr, address.ip6.bytes);
                printf("addr: [%s]\n", printedAddr);
            }
                missingKey();
        }
    }

    for (;;) {
        Random_bytes(rand, address.key, 32);
        // Brute force for keys until one matches FC00:/8
        if (AddressCalc_addressForPublicKey(address.ip6.bytes, address.key)
            && (mostSignificantAddressSpaceByte == -1
                || address.ip6.bytes[8] == mostSignificantAddressSpaceByte))
        {

            uint8_t publicKeyHex[65];
            Hex_encode(publicKeyHex, 65, address.key, 32);
            printf("created new key: [%s]\n", publicKeyHex);

            address.path = path;
            return Allocator_clone(alloc, &address);
        }
    }
}

static struct Address* randomIp(int* hops)
{
    return createAddress(-1, hops);
}

// This creates a random address which is a peer
static struct Address* randomAddress()
{
    return randomIp((int[]){0,1}/*0x13*/);
}