Esempio n. 1
0
static uint8_t sendMessage(struct Message* message, struct Interface* iface)
{
    struct UDPAddrInterface_pvt* context =
        Identity_cast((struct UDPAddrInterface_pvt*) iface->senderContext);

    struct Sockaddr_storage addrStore;
    Message_pop(message, &addrStore, context->pub.addr->addrLen);
    Assert_true(addrStore.addr.addrLen == context->pub.addr->addrLen);

    if (Socket_sendto(context->socket,
                      message->bytes,
                      message->length,
                      0,
                      &addrStore.addr) < 0)
    {
        switch (Errno_get()) {
            case Errno_EMSGSIZE:
                return Error_OVERSIZE_MESSAGE;

            case Errno_ENOBUFS:
            case Errno_EAGAIN:
                return Error_LINK_LIMIT_EXCEEDED;

            default:;
                Log_info(context->logger, "Got error sending to socket [%s]",
                         Errno_getString());
        }
    }
    return 0;
}
Esempio n. 2
0
void TUNConfigurator_setMTU(const char* interfaceName,
                            uint32_t mtu,
                            struct Log* logger,
                            struct Except* eh)
{
    int s = socket(AF_INET6, SOCK_DGRAM, 0);

    if (s < 0) {
        Except_raise(eh,
                     TUNConfigurator_ERROR_GETTING_ADMIN_SOCKET,
                     "socket() failed [%s]",
                     Errno_getString());
    }


    struct ifreq ifRequest;

    strncpy(ifRequest.ifr_name, interfaceName, IFNAMSIZ);
    ifRequest.ifr_mtu = mtu;

    Log_info(logger, "Setting MTU for device [%s] to [%u] bytes.", interfaceName, mtu);

    if (ioctl(s, SIOCSIFMTU, &ifRequest) < 0) {
       enum Errno err = Errno_get();
       close(s);
       Except_raise(eh,
                    TUNConfigurator_setMTU_INTERNAL,
                    "ioctl(SIOCSIFMTU) failed [%s]",
                    Errno_strerror(err));
    }
}
Esempio n. 3
0
static void newInterface2(struct Context* ctx,
                          struct Sockaddr* addr,
                          String* txid)
{
    struct Allocator* const alloc = Allocator_child(ctx->allocator);
    struct UDPInterface* udpIf = NULL;
    struct Jmp jmp;
    Jmp_try(jmp) {
        udpIf = UDPInterface_new(ctx->eventBase, addr, alloc, &jmp.handler, ctx->logger, ctx->ic);
    } Jmp_catch {
        String* errStr = String_CONST(jmp.message);
        Dict out = Dict_CONST(String_CONST("error"), String_OBJ(errStr), NULL);

        if (jmp.code == UDPInterface_new_SOCKET_FAILED
            || jmp.code == UDPInterface_new_BIND_FAILED)
        {
            char* err = Errno_getString();
            Dict out2 = Dict_CONST(String_CONST("cause"), String_OBJ(String_CONST(err)), out);
            Admin_sendMessage(&out2, txid, ctx->admin);
        } else {
            Admin_sendMessage(&out, txid, ctx->admin);
        }

        Allocator_free(alloc);
    }

    // sizeof(struct UDPInterface*) the size of a pointer.
    ctx->ifaces = Allocator_realloc(ctx->allocator,
                                    ctx->ifaces,
                                    sizeof(struct UDPInterface*) * (ctx->ifCount + 1));
    ctx->ifaces[ctx->ifCount] = udpIf;

    Dict out = Dict_CONST(
        String_CONST("error"), String_OBJ(String_CONST("none")), Dict_CONST(
        String_CONST("interfaceNumber"), Int_OBJ(ctx->ifCount), NULL
    ));

    Admin_sendMessage(&out, txid, ctx->admin);
    ctx->ifCount++;
}
Esempio n. 4
0
/**
 * Initialize the core.
 *
 * @param coreBinaryPath the path to the core binary.
 * @param toCore a pointer to an int which will be set to the
 *               file descriptor for writing to the core.
 * @param fromCore a pointer to an int which will be set to the
 *                 file descriptor for reading from the core.
 * @param eh an exception handler in case something goes wrong.
 */
static void initCore(char* coreBinaryPath,
                     int* toCore,
                     int* fromCore,
                     struct Except* eh)
{
    int pipes[2][2];
    if (Pipe_createUniPipe(pipes[0]) || Pipe_createUniPipe(pipes[1])) {
        Except_raise(eh, -1, "Failed to create pipes [%s]", Errno_getString());
    }

    // Pipes used in the core process.
    #define TO_ANGEL (pipes[1][1])
    #define FROM_ANGEL (pipes[0][0])

    // Pipes used in the angel process (here).
    #define TO_CORE (pipes[0][1])
    #define FROM_CORE (pipes[1][0])

    char toAngel[32];
    char fromAngel[32];
    snprintf(toAngel, 32, "%u", TO_ANGEL);
    snprintf(fromAngel, 32, "%u", FROM_ANGEL);
    char* args[] = { "core", toAngel, fromAngel, NULL };

    FILE* file;
    if ((file = fopen(coreBinaryPath, "r")) != NULL) {
        fclose(file);
    } else {
        Except_raise(eh, -1, "Can't open core executable [%s] for reading.", coreBinaryPath);
    }

    if (Process_spawn(coreBinaryPath, args)) {
        Except_raise(eh, -1, "Failed to spawn core process.");
    }

    *toCore = TO_CORE;
    *fromCore = FROM_CORE;
}
Esempio n. 5
0
/** @return a string representing the address and port to connect to. */
static String* initAngel(int fromAngel,
                         int toAngel,
                         int corePipes[2][2],
                         struct PipeInterface** piOut,
                         struct EventBase* eventBase,
                         struct Log* logger,
                         struct Allocator* alloc,
                         struct Random* rand)
{
    #define TO_CORE (corePipes[0][1])
    #define FROM_CORE (corePipes[1][0])
    #define TO_ANGEL_AS_CORE (corePipes[1][1])
    #define FROM_ANGEL_AS_CORE (corePipes[0][0])

    Dict core = Dict_CONST(
        String_CONST("fromCore"), Int_OBJ(FROM_CORE), Dict_CONST(
        String_CONST("toCore"), Int_OBJ(TO_CORE), NULL
    ));
    Dict admin = Dict_CONST(
        String_CONST("bind"), String_OBJ(String_CONST("127.0.0.1")), Dict_CONST(
        String_CONST("core"), Dict_OBJ(&core), Dict_CONST(
        String_CONST("pass"), String_OBJ(String_CONST("abcd")), NULL
    )));
    Dict message = Dict_CONST(
        String_CONST("admin"), Dict_OBJ(&admin), NULL
    );

    struct Allocator* tempAlloc;
    BufferAllocator_STACK(tempAlloc, 1024);

    #define BUFFER_SZ 1023
    uint8_t buff[BUFFER_SZ + 1] = {0};
    struct Writer* w = ArrayWriter_new(buff, BUFFER_SZ, tempAlloc);
    StandardBencSerializer_get()->serializeDictionary(w, &message);

    Log_info(logger, "Writing intial configuration to angel on [%d] config: [%s]", toAngel, buff);
    write(toAngel, buff, w->bytesWritten(w));

    // This is angel->core data, we can throw this away.
    //Waiter_getData(buff, BUFFER_SZ, fromAngel, eventBase, NULL);
    //Log_info(logger, "Init message from angel to core: [%s]", buff);
    Bits_memset(buff, 0, BUFFER_SZ);

    struct PipeInterface* pi =
        PipeInterface_new(FROM_ANGEL_AS_CORE, TO_ANGEL_AS_CORE, eventBase, logger, alloc, rand);
    *piOut = pi;

    Log_info(logger, "PipeInterface [%p] is now ready.", (void*)pi);

    // Make sure the angel sends data to the core.
    InterfaceWaiter_waitForData(&pi->generic, eventBase, alloc, NULL);

    // Send response on behalf of core.
    char coreToAngelResponse[128] = "           PADDING              "
        "\xff\xff\xff\xff"
        "d"
          "5:error" "4:none"
        "e";

    char* start = strchr(coreToAngelResponse, '\xff');
    struct Message m = {
        .bytes = (uint8_t*) start,
        .length = strlen(start),
        .padding = start - coreToAngelResponse
    };
    pi->generic.sendMessage(&m, &pi->generic);

    // This is angel->client data, it will tell us which port was bound.
    Waiter_getData(buff, BUFFER_SZ, fromAngel, eventBase, NULL);

    printf("Response from angel to client: [%s]\n", buff);

    struct Reader* reader = ArrayReader_new(buff, BUFFER_SZ, tempAlloc);
    Dict configStore;
    Dict* config = &configStore;
    Assert_true(!StandardBencSerializer_get()->parseDictionary(reader, tempAlloc, config));

    Dict* responseAdmin = Dict_getDict(config, String_CONST("admin"));
    String* bind = Dict_getString(responseAdmin, String_CONST("bind"));
    Assert_true(bind);

    return String_clone(bind, alloc);
}

/**
 * This spawns itself as the Angel process which spawns itself again as the core process.
 * The "core process" pipes all of its inputs back to the originating process
 */

struct AdminTestFramework* AdminTestFramework_setUp(int argc, char** argv)
{
    if (argc > 1 && !strcmp("angel", argv[1])) {
        exit(AngelInit_main(argc, argv));
    }

    struct Allocator* alloc = CanaryAllocator_new(MallocAllocator_new(1<<20), NULL);

    struct Writer* logwriter = FileWriter_new(stdout, alloc);
    Assert_always(logwriter);
    struct Log* logger = WriterLog_new(logwriter, alloc);

    struct EventBase* eventBase = EventBase_new(alloc);
    struct Random* rand = Random_new(alloc, NULL);

    int fromAngel;
    int toAngel;
    int corePipes[2][2];
    if (Pipe_createUniPipe(corePipes[0]) || Pipe_createUniPipe(corePipes[1])) {
        Except_raise(NULL, -1, "Failed to create pipes [%s]", Errno_getString());
    }
    spawnAngel(&fromAngel, &toAngel);

    struct PipeInterface* pi;
    String* addrStr =
        initAngel(fromAngel, toAngel, corePipes, &pi, eventBase, logger, alloc, rand);

    Log_info(logger, "Angel initialized.");

    String* password = String_new("abcd", alloc);
    struct Admin* admin =
        Admin_new(&pi->generic, alloc, logger, eventBase, password);


    // Now setup the client.

    struct sockaddr_storage addr;
    int addrLen = sizeof(struct sockaddr_storage);
    Bits_memset(&addr, 0, sizeof(struct sockaddr_storage));
    Assert_true(!evutil_parse_sockaddr_port(addrStr->bytes, (struct sockaddr*) &addr, &addrLen));

    struct AdminClient* client =
        AdminClient_new((uint8_t*) &addr, addrLen, password, eventBase, logger, alloc);

    Assert_always(client);

    return alloc->clone(sizeof(struct AdminTestFramework), alloc, &(struct AdminTestFramework) {
        .admin = admin,
        .client = client,
        .alloc = alloc,
        .eventBase = eventBase,
        .logger = logger,
        .addr = alloc->clone(addrLen, alloc, &addr),
        .addrLen = addrLen,
        .angelInterface = &pi->generic
    });
}
Esempio n. 6
0
int main(int argc, char** argv)
{
    #ifdef Log_KEYS
        fprintf(stderr, "Log_LEVEL = KEYS, EXPECT TO SEE PRIVATE KEYS IN YOUR LOGS!\n");
    #endif

    Assert_true(argc > 0);
    struct Except* eh = NULL;

    // Allow it to allocate 4MB
    struct Allocator* allocator = MallocAllocator_new(1<<22);
    struct Random* rand = Random_new(allocator, NULL, eh);
    struct EventBase* eventBase = EventBase_new(allocator);

    if (argc == 2) {
        // one argument
        if (strcmp(argv[1], "--help") == 0) {
            return usage(argv[0]);
        } else if (strcmp(argv[1], "--genconf") == 0) {
            return genconf(rand);
        } else if (strcmp(argv[1], "--pidfile") == 0) {
            // Performed after reading the configuration
        } else if (strcmp(argv[1], "--reconf") == 0) {
            // Performed after reading the configuration
        } else if (strcmp(argv[1], "--bench") == 0) {
            return benchmark();
        } else if (strcmp(argv[1], "--version") == 0) {
            //printf("Version ID: %s\n", RouterModule_gitVersion());
            return 0;
        } else {
            fprintf(stderr, "%s: unrecognized option '%s'\n", argv[0], argv[1]);
            fprintf(stderr, "Try `%s --help' for more information.\n", argv[0]);
            return -1;
        }
    } else if (argc >  2) {
        // more than one argument?
        fprintf(stderr, "%s: too many arguments\n", argv[0]);
        fprintf(stderr, "Try `%s --help' for more information.\n", argv[0]);
        return -1;
    }

    if (isatty(STDIN_FILENO)) {
        // We were started from a terminal
        // The chances an user wants to type in a configuration
        // bij hand are pretty slim so we show him the usage
        return usage(argv[0]);
    } else {
        // We assume stdin is a configuration file and that we should
        // start routing
    }

    struct Reader* stdinReader = FileReader_new(stdin, allocator);
    Dict config;
    if (JsonBencSerializer_get()->parseDictionary(stdinReader, allocator, &config)) {
        fprintf(stderr, "Failed to parse configuration.\n");
        return -1;
    }

    struct Writer* logWriter = FileWriter_new(stdout, allocator);
    struct Log* logger = WriterLog_new(logWriter, allocator);

    // --------------------- Setup Pipes to Angel --------------------- //
    int pipeToAngel[2];
    int pipeFromAngel[2];
    if (Pipe_createUniPipe(pipeToAngel) || Pipe_createUniPipe(pipeFromAngel)) {
        Except_raise(eh, -1, "Failed to create pipes to angel [%s]", Errno_getString());
    }

    char pipeToAngelStr[8];
    snprintf(pipeToAngelStr, 8, "%d", pipeToAngel[0]);
    char pipeFromAngelStr[8];
    snprintf(pipeFromAngelStr, 8, "%d", pipeFromAngel[1]);
    char* args[] = { "angel", pipeToAngelStr, pipeFromAngelStr, NULL };

    // --------------------- Spawn Angel --------------------- //
    String* privateKey = Dict_getString(&config, String_CONST("privateKey"));

    String* corePath = getCorePath(allocator);
    if (!corePath) {
        Except_raise(eh, -1, "Can't find a usable cjdns core executable, "
                             "make sure it is in the same directory as cjdroute");
    }

    if (!privateKey) {
        Except_raise(eh, -1, "Need to specify privateKey.");
    }
    Log_info(logger, "Forking angel to background.");
    Process_spawn(corePath->bytes, args);

    // --------------------- Get Admin  --------------------- //
    Dict* configAdmin = Dict_getDict(&config, String_CONST("admin"));
    String* adminPass = Dict_getString(configAdmin, String_CONST("password"));
    String* adminBind = Dict_getString(configAdmin, String_CONST("bind"));
    if (!adminPass) {
        adminPass = String_newBinary(NULL, 32, allocator);
        Random_base32(rand, (uint8_t*) adminPass->bytes, 32);
        adminPass->len = strlen(adminPass->bytes);
    }
    if (!adminBind) {
        adminBind = String_new("127.0.0.1:0", allocator);
    }

    // --------------------- Get user for angel to setuid() ---------------------- //
    String* securityUser = NULL;
    List* securityConf = Dict_getList(&config, String_CONST("security"));
    for (int i = 0; i < List_size(securityConf); i++) {
        securityUser = Dict_getString(List_getDict(securityConf, i), String_CONST("setuser"));
        if (securityUser) {
            int64_t* ea = Dict_getInt(List_getDict(securityConf, i), String_CONST("exemptAngel"));
            if (ea && *ea) {
                securityUser = NULL;
            }
            break;
        }
    }

    // --------------------- Pre-Configure Angel ------------------------- //
    Dict* preConf = Dict_new(allocator);
    Dict* adminPreConf = Dict_new(allocator);
    Dict_putDict(preConf, String_CONST("admin"), adminPreConf, allocator);
    Dict_putString(adminPreConf, String_CONST("core"), corePath, allocator);
    Dict_putString(preConf, String_CONST("privateKey"), privateKey, allocator);
    Dict_putString(adminPreConf, String_CONST("bind"), adminBind, allocator);
    Dict_putString(adminPreConf, String_CONST("pass"), adminPass, allocator);
    if (securityUser) {
        Dict_putString(adminPreConf, String_CONST("user"), securityUser, allocator);
    }

    #define CONFIG_BUFF_SIZE 1024
    uint8_t buff[CONFIG_BUFF_SIZE] = {0};
    struct Writer* toAngelWriter = ArrayWriter_new(buff, CONFIG_BUFF_SIZE - 1, allocator);
    if (StandardBencSerializer_get()->serializeDictionary(toAngelWriter, preConf)) {
        Except_raise(eh, -1, "Failed to serialize pre-configuration");
    }
    write(pipeToAngel[1], buff, toAngelWriter->bytesWritten(toAngelWriter));
    Log_keys(logger, "Sent [%s] to angel process.", buff);

    // --------------------- Get Response from Angel --------------------- //

    uint32_t amount = Waiter_getData(buff, CONFIG_BUFF_SIZE, pipeFromAngel[0], eventBase, eh);
    Dict responseFromAngel;
    struct Reader* responseFromAngelReader = ArrayReader_new(buff, amount, allocator);
    if (StandardBencSerializer_get()->parseDictionary(responseFromAngelReader,
                                                      allocator,
                                                      &responseFromAngel))
    {
        Except_raise(eh, -1, "Failed to parse pre-configuration response [%s]", buff);
    }

    // --------------------- Get Admin Addr/Port/Passwd --------------------- //
    Dict* responseFromAngelAdmin = Dict_getDict(&responseFromAngel, String_CONST("admin"));
    adminBind = Dict_getString(responseFromAngelAdmin, String_CONST("bind"));

    if (!adminBind) {
        Except_raise(eh, -1, "didn't get address and port back from angel");
    }
    struct Sockaddr_storage adminAddr;
    if (Sockaddr_parse(adminBind->bytes, &adminAddr)) {
        Except_raise(eh, -1, "Unable to parse [%s] as an ip address port, eg: 127.0.0.1:11234",
                     adminBind->bytes);
    }

    // sanity check
    Assert_true(EventBase_eventCount(eventBase) == 0);

    // --------------------- Configuration ------------------------- //
    Configurator_config(&config,
                        &adminAddr.addr,
                        adminPass,
                        eventBase,
                        logger,
                        allocator);

    return 0;
}
Esempio n. 7
0
void TUNConfigurator_setIpAddress(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_raise(eh,
                     TUNConfigurator_setIpAddress_INTERNAL,
                     "bad IPv6 address [%s]",
                     gai_strerror(err));
    }

    Bits_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_raise(eh,
                     TUNConfigurator_setIpAddress_INTERNAL,
                     "socket() failed [%s]",
                     Errno_getString());
    }

    if (ioctl(s, SIOCAIFADDR_IN6, &in6_addreq) < 0) {
        enum Errno err = Errno_get();
        close(s);
        Except_raise(eh,
                     TUNConfigurator_setIpAddress_INTERNAL,
                     "ioctl(SIOCAIFADDR) failed [%s]",
                     Errno_strerror(err));
    }

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

    close(s);
}