static void allowConnection(Dict* args,
                            void* vcontext,
                            String* txid,
                            struct Allocator* requestAlloc)
{
    struct Context* context = (struct Context*) vcontext;
    String* publicKeyOfAuthorizedNode =
        Dict_getString(args, String_CONST("publicKeyOfAuthorizedNode"));
    String* ip6Address = Dict_getString(args, String_CONST("ip6Address"));
    int64_t* ip6Prefix = Dict_getInt(args, String_CONST("ip6Prefix"));
    String* ip4Address = Dict_getString(args, String_CONST("ip4Address"));
    int64_t* ip4Prefix = Dict_getInt(args, String_CONST("ip4Prefix"));
    uint8_t pubKey[32];
    uint8_t ip6Addr[16];

    struct Sockaddr_storage ip6ToGive;
    struct Sockaddr_storage ip4ToGive;

    char* error;
    int ret;
    if (!ip6Address && !ip4Address) {
        error = "Must specify ip6Address or ip4Address";
    } else if ((ret = Key_parse(publicKeyOfAuthorizedNode, pubKey, ip6Addr)) != 0) {
        error = Key_parse_strerror(ret);
    } else if (ip6Prefix && !ip6Address) {
        error = "Must specify ip6Address with ip6Prefix";
    } else if (ip6Prefix && (*ip6Prefix > 128 || *ip6Prefix < 0)) {
        error = "ip6Prefix out of range: must be 0 to 128";
    } else if (ip4Prefix && (*ip4Prefix > 32 || *ip4Prefix < 0)) {
        error = "ip4Prefix out of range: must be 0 to 32";
    } else if (ip4Prefix && !ip4Address) {
        error = "Must specify ip4Address with ip4Prefix";
    } else if (ip6Address
        && (Sockaddr_parse(ip6Address->bytes, &ip6ToGive)
            || Sockaddr_getFamily(&ip6ToGive.addr) != Sockaddr_AF_INET6))
    {
        error = "malformed ip6Address";
    } else if (ip4Address
        && (Sockaddr_parse(ip4Address->bytes, &ip4ToGive)
            || Sockaddr_getFamily(&ip4ToGive.addr) != Sockaddr_AF_INET))
    {
        error = "malformed ip4Address";
    } else {
        int conn = IpTunnel_allowConnection(pubKey,
                                            (ip6Address) ? &ip6ToGive.addr : NULL,
                                            (ip6Prefix) ? (uint8_t) (*ip6Prefix) : 0,
                                            (ip4Address) ? &ip4ToGive.addr : NULL,
                                            (ip4Prefix) ? (uint8_t) (*ip4Prefix) : 0,
                                            context->ipTun);
        sendResponse(conn, txid, context->admin);
        return;
    }

    sendError(error, txid, context->admin);
}
Beispiel #2
0
static void checkAddressAndPrefix(struct Sockaddr* sa,
                                  int* addrFam,
                                  char** printedAddr,
                                  void** addr,
                                  struct Allocator* alloc,
                                  struct Except* eh)
{
    *printedAddr = Sockaddr_print(sa, alloc);
    *addrFam = Sockaddr_getFamily(sa);
    if (*addrFam != Sockaddr_AF_INET && *addrFam != Sockaddr_AF_INET6) {
        Except_throw(eh, "Unknown address type for address [%s]", *printedAddr);
    }
    int prefixMax = (*addrFam == Sockaddr_AF_INET6) ? 128 : 32;
    if (!(sa->flags & Sockaddr_flags_PREFIX)) {
        sa->prefix = prefixMax;
    }
    if (sa->prefix > prefixMax) {
        Except_throw(eh, "prefix [%u] must be less than %d", sa->prefix, prefixMax);
    }

    int len = Sockaddr_getAddress(sa, addr);
    if (len < 0 || len != prefixMax / 8) {
        Except_throw(eh, "Invalid sockaddr [%s]", *printedAddr);
    }
}
Beispiel #3
0
void NetDev_addAddress(const char* ifName,
                       struct Sockaddr* sa,
                       int prefixLen,
                       struct Log* logger,
                       struct Except* eh)
{
    int addrFam = Sockaddr_getFamily(sa);

    struct Allocator* alloc;
    BufferAllocator_STACK(alloc, 4096);
    char* printedAddr = Sockaddr_print(sa, alloc);
    if (addrFam != Sockaddr_AF_INET && addrFam != Sockaddr_AF_INET6) {
        Except_throw(eh, "Unknown address type for address [%s]", printedAddr);
    }

    int prefixMax = (addrFam == Sockaddr_AF_INET6) ? 128 : 32;
    if (prefixLen < 0 || prefixLen > prefixMax) {
        Except_throw(eh, "prefixLen [%d] must be greater than 0 and less than %d",
                     prefixLen, prefixMax);
    }

    void* addr;
    int len = Sockaddr_getAddress(sa, &addr);
    if (len < 0 || len != prefixMax / 8) {
        Except_throw(eh, "Invalid sockaddr [%s]", printedAddr);
    }

    Log_info(logger, "Setting IP address [%s/%d] on interface [%s]",
             printedAddr, prefixLen, ifName);

    NetPlatform_addAddress(ifName, addr, prefixLen, addrFam, logger, eh);
}
Beispiel #4
0
static void addRemoveSomething(Dict* args,
                               void* vcontext,
                               String* txid,
                               struct Allocator* requestAlloc,
                               enum addRemoveSomething_What what)
{
    struct RouteGen_admin_Ctx* ctx = Identity_check((struct RouteGen_admin_Ctx*) vcontext);
    String* route = Dict_getString(args, String_CONST("route"));
    char* error = NULL;

    struct Sockaddr_storage ss;
    if (route->len > 63) {
        error = "parse_failed";
    }
    if (!error) {
        if (Sockaddr_parse(route->bytes, &ss)) {
            error = "parse_failed";
        } else {
            int family = Sockaddr_getFamily(&ss.addr);
            if (family != Sockaddr_AF_INET && family != Sockaddr_AF_INET6) {
                error = "unexpected_af";
            }
        }
    }
    int retVal = -1;
    Dict* out = Dict_new(requestAlloc);
    if (!error) {
        switch (what) {
            case addRemoveSomething_What_ADD_EXCEPTION:
                RouteGen_addException(ctx->rg, &ss.addr); break;
            case addRemoveSomething_What_ADD_PREFIX:
                RouteGen_addPrefix(ctx->rg, &ss.addr); break;
            case addRemoveSomething_What_ADD_LOCALPREFIX:
                RouteGen_addLocalPrefix(ctx->rg, &ss.addr); break;
            case addRemoveSomething_What_RM_EXCEPTION:
                retVal = RouteGen_removeException(ctx->rg, &ss.addr); break;
            case addRemoveSomething_What_RM_PREFIX:
                retVal = RouteGen_removePrefix(ctx->rg, &ss.addr); break;
            case addRemoveSomething_What_RM_LOCALPREFIX:
                retVal = RouteGen_removeLocalPrefix(ctx->rg, &ss.addr); break;
            default: Assert_failure("invalid op");
        }
        if (!retVal) {
            error = "no_such_route";
        } else {
            error = "none";
        }
    }
    Dict_putString(out,
                   String_new("error", requestAlloc),
                   String_new(error, requestAlloc),
                   requestAlloc);
    Admin_sendMessage(out, txid, ctx->admin);
}
Beispiel #5
0
/**
 * Parse out an address.
 *
 * @param out a pointer to a byte array which will be set to the bytes of the ipv6 address.
 * @param hexAddr a string representation of the ipv6 address such as:
 *                "fc4f:630d:e499:8f5b:c49f:6e6b:01ae:3120".
 * @return 0 if successful, -1 if the hexAddr is malformed.
 */
int AddrTools_parseIp(uint8_t out[16], const uint8_t hexAddr[40])
{
    struct Sockaddr_storage ss;
    if (Sockaddr_parse((const char*) hexAddr, &ss)
        || Sockaddr_getFamily(&ss.addr) != Sockaddr_AF_INET6)
    {
        return -1;
    }
    uint8_t* addr = NULL;
    Sockaddr_getAddress(&ss.addr, &addr);
    Bits_memcpy(out, addr, 16);
    return 0;
}
Beispiel #6
0
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 {
Beispiel #7
0
static void beginConnection(Dict* args,
                            void* vcontext,
                            String* txid,
                            struct Allocator* requestAlloc)
{
    struct Context* ctx = vcontext;

    String* password = Dict_getString(args, String_CONST("password"));
    String* publicKey = Dict_getString(args, String_CONST("publicKey"));
    String* address = Dict_getString(args, String_CONST("address"));
    int64_t* interfaceNumber = Dict_getInt(args, String_CONST("interfaceNumber"));
    uint32_t ifNum = (interfaceNumber) ? ((uint32_t) *interfaceNumber) : 0;
    String* peerName = Dict_getString(args, String_CONST("peerName"));
    String* error = NULL;

    Log_debug(ctx->logger, "Peering with [%s]", publicKey->bytes);

    struct Sockaddr_storage ss;
    uint8_t pkBytes[32];
    int ret;
    if (interfaceNumber && *interfaceNumber < 0) {
        error = String_CONST("negative interfaceNumber");

    } else if ((ret = Key_parse(publicKey, pkBytes, NULL))) {
        error = String_CONST(Key_parse_strerror(ret));

    } else if (Sockaddr_parse(address->bytes, &ss)) {
        error = String_CONST("unable to parse ip address and port.");

    } else if (Sockaddr_getFamily(&ss.addr) != Sockaddr_getFamily(ctx->udpIf->addr)) {
        error = String_CONST("different address type than this socket is bound to.");

    } else {

        struct Sockaddr* addr = &ss.addr;
        char* addrPtr = NULL;
        int addrLen = Sockaddr_getAddress(&ss.addr, &addrPtr);
        Assert_true(addrLen > 0);
        struct Allocator* tempAlloc = Allocator_child(ctx->alloc);
        if (Bits_isZero(addrPtr, addrLen)) {
            // unspec'd address, convert to loopback
            if (Sockaddr_getFamily(addr) == Sockaddr_AF_INET) {
                addr = Sockaddr_clone(Sockaddr_LOOPBACK, tempAlloc);
            } else if (Sockaddr_getFamily(addr) == Sockaddr_AF_INET6) {
                addr = Sockaddr_clone(Sockaddr_LOOPBACK6, tempAlloc);
            } else {
                Assert_failure("Sockaddr which is not AF_INET nor AF_INET6");
            }
            Sockaddr_setPort(addr, Sockaddr_getPort(&ss.addr));
        }

        int ret = InterfaceController_bootstrapPeer(
            ctx->ic, ifNum, pkBytes, addr, password, peerName, ctx->alloc);

        Allocator_free(tempAlloc);

        if (ret) {
            switch(ret) {
                case InterfaceController_bootstrapPeer_BAD_IFNUM:
                    error = String_CONST("no such interface for interfaceNumber");
                    break;

                case InterfaceController_bootstrapPeer_BAD_KEY:
                    error = String_CONST("invalid cjdns public key.");
                    break;

                case InterfaceController_bootstrapPeer_OUT_OF_SPACE:
                    error = String_CONST("no more space to register with the switch.");
                    break;

                default:
                    error = String_CONST("unknown error");
                    break;
            }
        } else {
            error = String_CONST("none");
        }
    }

    Dict out = Dict_CONST(String_CONST("error"), String_OBJ(error), NULL);
    Admin_sendMessage(&out, txid, ctx->admin);
}