Exemplo n.º 1
0
static void ipTunnel(Dict* ifaceConf, struct Allocator* tempAlloc, struct Context* ctx)
{
    List* incoming = Dict_getList(ifaceConf, String_CONST("allowedConnections"));
    Dict* d;
    for (int i = 0; (d = List_getDict(incoming, i)) != NULL; i++) {
        String* key = Dict_getString(d, String_CONST("publicKey"));
        String* ip4 = Dict_getString(d, String_CONST("ip4Address"));
        String* ip6 = Dict_getString(d, String_CONST("ip6Address"));
        if (!key) {
            Log_critical(ctx->logger, "In router.ipTunnel.allowedConnections[%d]"
                                      "'publicKey' required.", i);
            exit(1);
        }
        if (!ip4 && !ip6) {
            Log_critical(ctx->logger, "In router.ipTunnel.allowedConnections[%d]"
                                       "either ip4Address or ip6Address required.", i);
            exit(1);
        }
        Log_debug(ctx->logger, "Allowing IpTunnel connections from [%s]", key->bytes);
        Dict_putString(d, String_CONST("publicKeyOfAuthorizedNode"), key, tempAlloc);
        rpcCall0(String_CONST("IpTunnel_allowConnection"), d, ctx, tempAlloc, true);
    }

    List* outgoing = Dict_getList(ifaceConf, String_CONST("outgoingConnections"));
    String* s;
    for (int i = 0; (s = List_getString(outgoing, i)) != NULL; i++) {
        Log_debug(ctx->logger, "Initiating IpTunnel connection to [%s]", s->bytes);
        Dict requestDict =
            Dict_CONST(String_CONST("publicKeyOfNodeToConnectTo"), String_OBJ(s), NULL);
        rpcCall0(String_CONST("IpTunnel_connectTo"), &requestDict, ctx, tempAlloc, true);
    }
}
Exemplo n.º 2
0
void Configurator_config(Dict* config,
                         struct sockaddr_storage* addr,
                         int addrLen,
                         String* adminPassword,
                         struct event_base* eventBase,
                         struct Log* logger,
                         struct Allocator* alloc)
{
    struct Allocator* tempAlloc = alloc->child(alloc);
    struct AdminClient* client =
        AdminClient_new(addr, addrLen, adminPassword, eventBase, logger, tempAlloc);

    struct Context ctx = { .logger = logger, .alloc = tempAlloc, .client = client };

    List* authedPasswords = Dict_getList(config, String_CONST("authorizedPasswords"));
    if (authedPasswords) {
        authorizedPasswords(authedPasswords, &ctx);
    }

    Dict* ifaces = Dict_getDict(config, String_CONST("interfaces"));
    udpInterface(ifaces, &ctx);

    Dict* routerConf = Dict_getDict(config, String_CONST("router"));
    Dict* iface = Dict_getDict(routerConf, String_CONST("interface"));
    tunInterface(iface, tempAlloc, &ctx);

    List* securityList = Dict_getList(config, String_CONST("security"));
    security(securityList, tempAlloc, &ctx);

    tempAlloc->free(tempAlloc);
}
Exemplo n.º 3
0
static void dns(Dict* dns, struct Context* ctx, struct Except* eh)
{
    List* servers = Dict_getList(dns, String_CONST("servers"));
    int count = List_size(servers);
    for (int i = 0; i < count; i++) {
        String* server = List_getString(servers, i);
        if (!server) {
            Except_throw(eh, "dns.servers[%d] is not a string", i);
        }
        Dict* d = Dict_new(ctx->alloc);
        Dict_putString(d, String_CONST("addr"), server, ctx->alloc);
        rpcCall(String_CONST("RainflyClient_addServer"), d, ctx, ctx->alloc);
    }

    List* keys = Dict_getList(dns, String_CONST("keys"));
    count = List_size(keys);
    for (int i = 0; i < count; i++) {
        String* key = List_getString(keys, i);
        if (!key) {
            Except_throw(eh, "dns.keys[%d] is not a string", i);
        }
        Dict* d = Dict_new(ctx->alloc);
        Dict_putString(d, String_CONST("ident"), key, ctx->alloc);
        rpcCall(String_CONST("RainflyClient_addKey"), d, ctx, ctx->alloc);
    }

    int64_t* minSigs = Dict_getInt(dns, String_CONST("minSignatures"));
    if (minSigs) {
        Dict* d = Dict_new(ctx->alloc);
        Dict_putInt(d, String_CONST("count"), *minSigs, ctx->alloc);
        rpcCall(String_CONST("RainflyClient_minSignatures"), d, ctx, ctx->alloc);
    }
}
Exemplo n.º 4
0
static void getSomething(Dict* args,
                         struct RouteGen_admin_Ctx* ctx,
                         String* txid,
                         struct Allocator* requestAlloc,
                         Dict* genRoutes)
{
    int page = getIntVal(args, String_CONST("page"));
    List* routes;
    if (getIntVal(args, String_CONST("ip6"))) {
        routes = Dict_getList(genRoutes, String_CONST("ipv6"));
    } else {
        routes = Dict_getList(genRoutes, String_CONST("ipv4"));
    }
    Assert_true(routes);
    List* outList = List_new(requestAlloc);
    bool more = false;
    for (int i = page * ROUTES_PER_PAGE, j = 0; i < List_size(routes) && j < ROUTES_PER_PAGE; j++) {
        String* route = List_getString(routes, i);
        Assert_true(route);
        List_addString(outList, route, requestAlloc);
        if (++i >= List_size(routes)) {
            more = false;
            break;
        }
        more = true;
    }
    Dict* out = Dict_new(requestAlloc);
    if (more) {
        Dict_putInt(out, String_new("more", requestAlloc), 1, requestAlloc);
    }
    Dict_putList(out, String_new("routes", requestAlloc), outList, requestAlloc);
    Admin_sendMessage(out, txid, ctx->admin);
}
Exemplo n.º 5
0
static bool checkArgs(Dict* args, struct Function* func, String* txid, struct Admin* admin)
{
    struct Dict_Entry* entry = *func->args;
    String* error = NULL;
    uint8_t buffer[1024];
    struct Allocator* alloc = BufferAllocator_new(buffer, 1024);
    while (entry != NULL) {
        String* key = (String*) entry->key;
        Assert_true(entry->val->type == Object_DICT);
        Dict* value = entry->val->as.dictionary;
        entry = entry->next;
        if (*Dict_getInt(value, String_CONST("required")) == 0) {
            continue;
        }
        String* type = Dict_getString(value, String_CONST("type"));
        if ((type == STRING && !Dict_getString(args, key))
            || (type == DICT && !Dict_getDict(args, key))
            || (type == INTEGER && !Dict_getInt(args, key))
            || (type == LIST && !Dict_getList(args, key)))
        {
            error = String_printf(alloc,
                                  "Entry [%s] is required and must be of type [%s]",
                                  key->bytes,
                                  type->bytes);
            break;
        }
    }
    if (error) {
        Dict d = Dict_CONST(String_CONST("error"), String_OBJ(error), NULL);
        Admin_sendMessage(&d, txid, admin);
    }
    return !error;
}
Exemplo n.º 6
0
void Configurator_config(Dict* config,
                         struct Sockaddr* sockAddr,
                         String* adminPassword,
                         struct EventBase* eventBase,
                         struct Log* logger,
                         struct Allocator* alloc)
{
    struct Allocator* tempAlloc = Allocator_child(alloc);
    struct UDPAddrIface* udp = UDPAddrIface_new(eventBase, NULL, alloc, NULL, logger);
    struct AdminClient* client =
        AdminClient_new(&udp->generic, sockAddr, adminPassword, eventBase, logger, tempAlloc);

    struct Context ctx = {
        .logger = logger,
        .alloc = tempAlloc,
        .client = client,
        .base = eventBase,
    };

    waitUntilPong(&ctx);

    List* authedPasswords = Dict_getList(config, String_CONST("authorizedPasswords"));
    if (authedPasswords) {
        authorizedPasswords(authedPasswords, &ctx);
    }

    Dict* ifaces = Dict_getDict(config, String_CONST("interfaces"));
    udpInterface(ifaces, &ctx);

    if (Defined(HAS_ETH_INTERFACE)) {
        ethInterface(ifaces, &ctx);
    }

    Dict* routerConf = Dict_getDict(config, String_CONST("router"));
    routerConfig(routerConf, tempAlloc, &ctx);

    List* secList = Dict_getList(config, String_CONST("security"));
    security(tempAlloc, secList, logger, &ctx);

    Log_debug(logger, "Cjdns started in the background");

    Allocator_free(tempAlloc);
}
Exemplo n.º 7
0
void Configurator_config(Dict* config,
                         struct Sockaddr* sockAddr,
                         String* adminPassword,
                         struct EventBase* eventBase,
                         struct Log* logger,
                         struct Allocator* alloc)
{
    struct Except* eh = NULL;
    struct Allocator* tempAlloc = Allocator_child(alloc);
    struct AdminClient* client =
        AdminClient_new(sockAddr, adminPassword, eventBase, logger, tempAlloc);

    struct Context ctx = {
        .logger = logger,
        .alloc = tempAlloc,
        .client = client,
        .base = eventBase,
    };

    List* authedPasswords = Dict_getList(config, String_CONST("authorizedPasswords"));
    if (authedPasswords) {
        authorizedPasswords(authedPasswords, &ctx);
    }

    Dict* ifaces = Dict_getDict(config, String_CONST("interfaces"));
    udpInterface(ifaces, &ctx);

    #ifdef HAS_ETH_INTERFACE
        ethInterface(ifaces, &ctx);
    #endif

    Dict* routerConf = Dict_getDict(config, String_CONST("router"));
    routerConfig(routerConf, tempAlloc, &ctx);

    List* securityList = Dict_getList(config, String_CONST("security"));
    security(securityList, tempAlloc, &ctx);

    Dict* dnsConf = Dict_getDict(config, String_CONST("dns"));
    dns(dnsConf, &ctx, eh);

    Allocator_free(tempAlloc);
}
Exemplo n.º 8
0
static void ethInterface(Dict* config, struct Context* ctx)
{
    List* ifaces = Dict_getList(config, String_CONST("ETHInterface"));
    if (!ifaces) {
        ifaces = List_new(ctx->alloc);
        List_addDict(ifaces, Dict_getDict(config, String_CONST("ETHInterface")), ctx->alloc);
    }

    uint32_t count = List_size(ifaces);

    for (uint32_t i = 0; i < count; i++) {
        Dict *eth = List_getDict(ifaces, i);
        if (!eth) { continue; }
        String* deviceStr = Dict_getString(eth, String_CONST("bind"));
        if (!deviceStr || !String_equals(String_CONST("all"), deviceStr)) { continue; }
        Log_info(ctx->logger, "Setting up all ETHInterfaces...");
        Dict* res = NULL;
        Dict* d = Dict_new(ctx->alloc);
        if (rpcCall0(String_CONST("ETHInterface_listDevices"), d, ctx, ctx->alloc, &res, false)) {
            Log_info(ctx->logger, "Getting device list failed");
            break;
        }
        List* devs = Dict_getList(res, String_CONST("devices"));
        uint32_t devCount = List_size(devs);
        for (uint32_t j = 0; j < devCount; j++) {
            Dict* d = Dict_new(ctx->alloc);
            String* deviceName = List_getString(devs, j);
            // skip loopback...
            if (String_equals(String_CONST("lo"), deviceName)) { continue; }
            Dict_putString(d, String_CONST("bindDevice"), deviceName, ctx->alloc);
            Dict* resp;
            Log_info(ctx->logger, "Creating new ETHInterface [%s]", deviceName->bytes);
            if (rpcCall0(String_CONST("ETHInterface_new"), d, ctx, ctx->alloc, &resp, false)) {
                Log_warn(ctx->logger, "Failed to create ETHInterface.");
                continue;
            }
            int ifNum = *(Dict_getInt(resp, String_CONST("interfaceNumber")));
            ethInterfaceSetBeacon(ifNum, eth, ctx);
        }
        return;
    }

    for (uint32_t i = 0; i < count; i++) {
        Dict *eth = List_getDict(ifaces, i);
        if (!eth) { continue; }
        // Setup the interface.
        String* deviceStr = Dict_getString(eth, String_CONST("bind"));
        Log_info(ctx->logger, "Setting up ETHInterface [%d].", i);
        Dict* d = Dict_new(ctx->alloc);
        if (deviceStr) {
            Log_info(ctx->logger, "Binding to device [%s].", deviceStr->bytes);
            Dict_putString(d, String_CONST("bindDevice"), deviceStr, ctx->alloc);
        }
        Dict* resp = NULL;
        if (rpcCall0(String_CONST("ETHInterface_new"), d, ctx, ctx->alloc, &resp, false)) {
            Log_warn(ctx->logger, "Failed to create ETHInterface.");
            continue;
        }
        int ifNum = *(Dict_getInt(resp, String_CONST("interfaceNumber")));
        ethInterfaceSetBeacon(ifNum, eth, ctx);

        // Make the connections.
        Dict* connectTo = Dict_getDict(eth, String_CONST("connectTo"));
        if (connectTo) {
            Log_info(ctx->logger, "ETHInterface should connect to a specific node.");
            struct Dict_Entry* entry = *connectTo;
            while (entry != NULL) {
                String* key = (String*) entry->key;
                if (entry->val->type != Object_DICT) {
                    Log_critical(ctx->logger, "interfaces.ETHInterface.connectTo: entry [%s] "
                                               "is not a dictionary type.", key->bytes);
                    exit(-1);
                }
                Dict* value = entry->val->as.dictionary;

                Log_keys(ctx->logger, "Attempting to connect to node [%s].", key->bytes);

                struct Allocator* perCallAlloc = Allocator_child(ctx->alloc);
                // Turn the dict from the config into our RPC args dict by filling in all
                // the arguments,
                Dict_putString(value, String_CONST("macAddress"), key, perCallAlloc);
                Dict_putInt(value, String_CONST("interfaceNumber"), ifNum, perCallAlloc);
                rpcCall(String_CONST("ETHInterface_beginConnection"), value, ctx, perCallAlloc);
                Allocator_free(perCallAlloc);

                entry = entry->next;
            }
        }
    }
}
Exemplo n.º 9
0
static void ipTunnel(Dict* ifaceConf, struct Allocator* tempAlloc, struct Context* ctx)
{
    List* incoming = Dict_getList(ifaceConf, String_CONST("allowedConnections"));
    if (incoming) {
        Dict* d;
        for (int i = 0; (d = List_getDict(incoming, i)) != NULL; i++) {
            String* key = Dict_getString(d, String_CONST("publicKey"));
            String* ip4 = Dict_getString(d, String_CONST("ip4Address"));
            // Note that the prefix length has to be a proper int in the config
            // (not quoted!)
            int64_t* ip4Prefix = Dict_getInt(d, String_CONST("ip4Prefix"));
            String* ip6 = Dict_getString(d, String_CONST("ip6Address"));
            int64_t* ip6Prefix = Dict_getInt(d, String_CONST("ip6Prefix"));
            if (!key) {
                Log_critical(ctx->logger, "In router.ipTunnel.allowedConnections[%d]"
                                          "'publicKey' required.", i);
                exit(1);
            }
            if (!ip4 && !ip6) {
                Log_critical(ctx->logger, "In router.ipTunnel.allowedConnections[%d]"
                                          "either 'ip4Address' or 'ip6Address' required.", i);
                exit(1);
            } else if (ip4Prefix && !ip4) {
                Log_critical(ctx->logger, "In router.ipTunnel.allowedConnections[%d]"
                                          "'ip4Address' required with 'ip4Prefix'.", i);
                exit(1);
            } else if (ip6Prefix && !ip6) {
                Log_critical(ctx->logger, "In router.ipTunnel.allowedConnections[%d]"
                                          "'ip6Address' required with 'ip6Prefix'.", i);
                exit(1);
            }
            Log_debug(ctx->logger, "Allowing IpTunnel connections from [%s]", key->bytes);

            if (ip4) {
                Log_debug(ctx->logger, "Issue IPv4 address %s", ip4->bytes);
                if (ip4Prefix) {
                    Log_debug(ctx->logger, "Issue IPv4 netmask/prefix length /%d",
                        (int) *ip4Prefix);
                } else {
                    Log_debug(ctx->logger, "Use default netmask/prefix length /0");
                }
            }

            if (ip6) {
                Log_debug(ctx->logger, "Issue IPv6 address [%s]", ip6->bytes);
                if (ip6Prefix) {
                    Log_debug(ctx->logger, "Issue IPv6 netmask/prefix length /%d",
                        (int) *ip6Prefix);
                } else {
                    Log_debug(ctx->logger, "Use default netmask/prefix length /0");
                }
            }

            Dict_putString(d, String_CONST("publicKeyOfAuthorizedNode"), key, tempAlloc);
            rpcCall0(String_CONST("IpTunnel_allowConnection"), d, ctx, tempAlloc, NULL, true);
        }
    }

    List* outgoing = Dict_getList(ifaceConf, String_CONST("outgoingConnections"));
    if (outgoing) {
        String* s;
        for (int i = 0; (s = List_getString(outgoing, i)) != NULL; i++) {
            Log_debug(ctx->logger, "Initiating IpTunnel connection to [%s]", s->bytes);
            Dict requestDict =
                Dict_CONST(String_CONST("publicKeyOfNodeToConnectTo"), String_OBJ(s), NULL);
            rpcCall0(String_CONST("IpTunnel_connectTo"), &requestDict, ctx, tempAlloc, NULL, true);
        }
    }
}
Exemplo n.º 10
0
static void udpInterface(Dict* config, struct Context* ctx)
{
    List* ifaces = Dict_getList(config, String_CONST("UDPInterface"));
    if (!ifaces) {
        ifaces = List_new(ctx->alloc);
        List_addDict(ifaces, Dict_getDict(config, String_CONST("UDPInterface")), ctx->alloc);
    }

    uint32_t count = List_size(ifaces);
    for (uint32_t i = 0; i < count; i++) {
        Dict *udp = List_getDict(ifaces, i);
        if (!udp) {
            continue;
        }
        // Setup the interface.
        String* bindStr = Dict_getString(udp, String_CONST("bind"));
        Dict* d = Dict_new(ctx->alloc);
        if (bindStr) {
            Dict_putString(d, String_CONST("bindAddress"), bindStr, ctx->alloc);
        }
        Dict* resp = NULL;
        rpcCall0(String_CONST("UDPInterface_new"), d, ctx, ctx->alloc, &resp, true);
        int ifNum = *(Dict_getInt(resp, String_CONST("interfaceNumber")));

        // Make the connections.
        Dict* connectTo = Dict_getDict(udp, String_CONST("connectTo"));
        if (connectTo) {
            struct Dict_Entry* entry = *connectTo;
            struct Allocator* perCallAlloc = Allocator_child(ctx->alloc);
            while (entry != NULL) {
                String* key = (String*) entry->key;
                if (entry->val->type != Object_DICT) {
                    Log_critical(ctx->logger, "interfaces.UDPInterface.connectTo: entry [%s] "
                                               "is not a dictionary type.", key->bytes);
                    exit(-1);
                }
                Dict* all =  entry->val->as.dictionary;
                Dict* value = Dict_new(perCallAlloc);
                String* pub_d = Dict_getString(all, String_CONST("publicKey"));
                String* pss_d = Dict_getString(all, String_CONST("password"));
                String* peerName_d = Dict_getString(all, String_CONST("peerName"));
                String* login_d = Dict_getString(all, String_CONST("login"));

                if ( !pub_d || !pss_d ) {
                    const char * error_name = "(unknown)";
                    if ( !pub_d ) {
                        error_name = "publicKey";
                    }
                    if ( !pss_d ) {
                        error_name = "password";
                    }
                    Log_warn(ctx->logger,
                        "Skipping peer: missing %s for peer [%s]", error_name, key->bytes);
                    if (abort_if_invalid_ref) {
                        Assert_failure("Invalid peer reference");
                    }
                    else {
                        entry = entry->next;
                        continue;
                    }
                }

                Dict_putString(value, String_CONST("publicKey"), pub_d, perCallAlloc);
                Dict_putString(value, String_CONST("password"), pss_d, perCallAlloc);
                Dict_putString(value, String_CONST("peerName"), peerName_d, perCallAlloc);
                Dict_putString(value, String_CONST("login"), login_d, perCallAlloc);

                Log_keys(ctx->logger, "Attempting to connect to node [%s].", key->bytes);
                key = String_clone(key, perCallAlloc);
                char* lastColon = CString_strrchr(key->bytes, ':');

                if (!Sockaddr_parse(key->bytes, NULL)) {
                    // it's a sockaddr, fall through
                } else if (lastColon) {
                    // try it as a hostname.
                    int port = atoi(lastColon+1);
                    if (!port) {
                        Log_critical(ctx->logger, "Couldn't get port number from [%s]", key->bytes);
                        exit(-1);
                    }
                    *lastColon = '\0';
                    struct Sockaddr* adr = Sockaddr_fromName(key->bytes, perCallAlloc);
                    if (adr != NULL) {
                        Sockaddr_setPort(adr, port);
                        key = String_new(Sockaddr_print(adr, perCallAlloc), perCallAlloc);
                    } else {
                        Log_warn(ctx->logger, "Failed to lookup hostname [%s]", key->bytes);
                        entry = entry->next;
                        continue;
                    }
                }
                struct Allocator* child = Allocator_child(ctx->alloc);
                struct Message* msg = Message_new(0, AdminClient_MAX_MESSAGE_SIZE + 256, child);
                int r = BencMessageWriter_writeDictTry(value, msg, NULL);

                const int max_reference_size = 298;
                if (r != 0 || msg->length > max_reference_size) {
                    Log_warn(ctx->logger, "Peer skipped:");
                    Log_warn(ctx->logger, "Too long peer reference for [%s]", key->bytes);
                    if (abort_if_invalid_ref) {
                        Assert_failure("Invalid peer reference");
                    }
                    else {
                        entry = entry->next;
                        continue;
                    }
                }
                Dict_putInt(value, String_CONST("interfaceNumber"), ifNum, perCallAlloc);
                Dict_putString(value, String_CONST("address"), key, perCallAlloc);
                rpcCall(String_CONST("UDPInterface_beginConnection"), value, ctx, perCallAlloc);
                entry = entry->next;
            }
            Allocator_free(perCallAlloc);
        }
    }
}
Exemplo n.º 11
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;
}
Exemplo n.º 12
0
int main(int argc, char** argv)
{
    if (argc > 1 && !strcmp("--genconf", argv[argc-1])) {
        genconf();
        return 0;
    }

    struct Allocator* alloc = MallocAllocator_new(1<<22);
    struct EventBase* base = EventBase_new(alloc);
    struct Writer* logWriter = FileWriter_new(stdout, alloc);
    struct Log* logger = WriterLog_new(logWriter, alloc);
    struct Random* rand = Random_new(alloc, logger, NULL);

    struct Reader* stdinReader = FileReader_new(stdin, alloc);
    Dict config;
    if (JsonBencSerializer_get()->parseDictionary(stdinReader, alloc, &config)) {
        Log_critical(logger, "Failed to parse configuration");
        return -1;
    }

    Dict* dns = Dict_getDict(&config, String_CONST("dns"));
    if (!dns) {
        Log_critical(logger, "No DNS in configuration");
        return -1;
    }

    struct Sockaddr_storage addr;
    Assert_true(!Sockaddr_parse("::", &addr));
    struct AddrInterface* ifaceB = UDPAddrInterface_new(base, &addr.addr, alloc, NULL, logger);
    struct RainflyClient* client = RainflyClient_new(ifaceB, base, rand, logger);

    String* bind = Dict_getString(dns, String_CONST("bind"));
    Assert_true(!Sockaddr_parse(bind ? bind->bytes : "[::]:5353", &addr));
    struct AddrInterface* iface = UDPAddrInterface_new(base, &addr.addr, alloc, NULL, logger);
    struct DNSServer* dnsServer = DNSServer_new(iface, logger, client);

    List* auth = Dict_getList(dns, String_CONST("authorities"));
    for (int i = 0; i < (int)List_size(auth); i++) {
        String* str = List_getString(auth, i);
        if (!str) {
            Log_warn(logger, "Element [%d] in [dns.authorities] list of wrong type", i);
            continue;
        }

        uint8_t key[32] = {0};
        if (str->len < 52 || Base32_decode(key, 32, str->bytes, 52) != 32) {
            Log_warn(logger, "Failed to parse key [%s]", str->bytes);
            continue;
        }

        if (RainflyClient_addKey(client, key)) {
            Log_warn(logger, "Failed to add key to RainflyClient [%s]", str->bytes);
        }
    }

    List* servers = Dict_getList(dns, String_CONST("servers"));
    for (int i = 0; i < (int)List_size(servers); i++) {
        String* str = List_getString(servers, i);
        if (!str) {
            Log_warn(logger, "Element [%d] in [dns.servers] list of wrong type", i);
            continue;
        }

        struct Sockaddr_storage node;
        if (Sockaddr_parse(str->bytes, &node)) {
            Log_warn(logger, "Failed to parse server name [%s]", str->bytes);
            continue;
        }

        if (RainflyClient_addServer(client, &node.addr)) {
            Log_warn(logger, "Failed to add server to RainflyClient [%s]", str->bytes);
        }
    }

    List* legacy = Dict_getList(dns, String_CONST("legacy"));
    for (int i = 0; i < (int)List_size(legacy); i++) {
        String* str = List_getString(legacy, i);
        if (!str) {
            Log_warn(logger, "Element [%d] in [dns.legacy] list of wrong type", i);
            continue;
        }

        struct Sockaddr_storage node;
        if (Sockaddr_parse(str->bytes, &node)) {
            Log_warn(logger, "Failed to parse legacy server name [%s]", str->bytes);
            continue;
        }

        if (DNSServer_addServer(dnsServer, &node.addr)) {
            Log_warn(logger, "Failed to add server to DNSServer [%s]", str->bytes);
        }
    }

    EventBase_beginLoop(base);
}
Exemplo n.º 13
0
static void udpInterface(Dict* config, struct Context* ctx)
{
    List* ifaces = Dict_getList(config, String_CONST("UDPInterface"));
    if (!ifaces) {
        ifaces = List_addDict(ifaces,
                Dict_getDict(config, String_CONST("UDPInterface")), ctx->alloc);
    }

    uint32_t count = List_size(ifaces);
    for (uint32_t i = 0; i < count; i++) {
        Dict *udp = List_getDict(ifaces, i);
        if (!udp) {
            continue;
        }
        // Setup the interface.
        String* bindStr = Dict_getString(udp, String_CONST("bind"));
        Dict* d = Dict_new(ctx->alloc);
        if (bindStr) {
            Dict_putString(d, String_CONST("bindAddress"), bindStr, ctx->alloc);
        }
        rpcCall(String_CONST("UDPInterface_new"), d, ctx, ctx->alloc);

        // Make the connections.
        Dict* connectTo = Dict_getDict(udp, String_CONST("connectTo"));
        if (connectTo) {
            struct Dict_Entry* entry = *connectTo;
            struct Allocator* perCallAlloc = Allocator_child(ctx->alloc);
            while (entry != NULL) {
                String* key = (String*) entry->key;
                if (entry->val->type != Object_DICT) {
                    Log_critical(ctx->logger, "interfaces.UDPInterface.connectTo: entry [%s] "
                                               "is not a dictionary type.", key->bytes);
                    exit(-1);
                }
                Dict* value = entry->val->as.dictionary;
                Log_keys(ctx->logger, "Attempting to connect to node [%s].", key->bytes);
                key = String_clone(key, perCallAlloc);
                char* lastColon = strrchr(key->bytes, ':');

                if (!Sockaddr_parse(key->bytes, NULL)) {
                    // it's a sockaddr, fall through
                } else if (lastColon) {
                    // try it as a hostname.
                    int port = atoi(lastColon+1);
                    if (!port) {
                        Log_critical(ctx->logger, "Couldn't get port number from [%s]", key->bytes);
                        exit(-1);
                    }
                    *lastColon = '\0';
                    struct Sockaddr* adr = Sockaddr_fromName(key->bytes, perCallAlloc);
                    if (adr != NULL) {
                        Sockaddr_setPort(adr, port);
                        key = String_new(Sockaddr_print(adr, perCallAlloc), perCallAlloc);
                    } else {
                        Log_warn(ctx->logger, "Failed to lookup hostname [%s]", key->bytes);
                        entry = entry->next;
                        continue;
                    }
                }
                Dict_putString(value, String_CONST("address"), key, perCallAlloc);
                rpcCall(String_CONST("UDPInterface_beginConnection"), value, ctx, perCallAlloc);
                entry = entry->next;
            }
            Allocator_free(perCallAlloc);
        }
    }
}
Exemplo n.º 14
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
    Crypto_init();
    Assert_true(argc > 0);

    if (argc == 2) {
        // one argument
        if (strcmp(argv[1], "--help") == 0) {
            return usage(argv[0]);
        } else if (strcmp(argv[1], "--genconf") == 0) {
            return genconf();
        } 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 event_base* eventBase = event_base_new();

    // Allow it to allocate 4MB
    struct Allocator* allocator = MallocAllocator_new(1<<22);
    struct Reader* reader = FileReader_new(stdin, allocator);
    Dict config;
    if (JsonBencSerializer_get()->parseDictionary(reader, allocator, &config)) {
        fprintf(stderr, "Failed to parse configuration.\n");
        return -1;
    }

    // Logging.
    struct Writer* logwriter = FileWriter_new(stdout, allocator);
    struct Log* logger = &(struct Log) { .writer = logwriter };


    // pid file
    String* pidFile = Dict_getString(&config, String_CONST("pidFile"));
    if (pidFile) {
        if (argc == 2 && strcmp(argv[1], "--pidfile") == 0) {
            printf("%s", pidFile->bytes);
            return 0;
        }
        Log_info(logger, "Writing pid of process to [%s].\n", pidFile->bytes);
        FILE* pf = fopen(pidFile->bytes, "w");
        if (!pf) {
            Log_critical(logger,
                          "Failed to open pid file [%s] for writing, errno=%d\n",
                          pidFile->bytes,
                          errno);
            return -1;
        }
        fprintf(pf, "%d", (int) getpid());
        fclose(pf);
    }

    // re-configure
    if (argc == 2 && strcmp(argv[1], "--reconf") == 0) {
        reconf(eventBase, &config, logger, allocator);
        return 0;
    }

    // ca, needed for admin.
    struct Address myAddr;
    uint8_t privateKey[32];
    parsePrivateKey(&config, &myAddr, privateKey);
    struct CryptoAuth* cryptoAuth =
        CryptoAuth_new(&config, allocator, privateKey, eventBase, logger);

    // Admin
    char* user = setUser(Dict_getList(&config, String_CONST("security")));
    struct Admin* admin = newAdmin(&config, user, logger, eventBase, allocator);

    struct SwitchCore* switchCore = SwitchCore_new(logger, allocator);
    struct DHTModuleRegistry* registry = DHTModuleRegistry_new(allocator);
    ReplyModule_register(registry, allocator);

    // Router
    struct Interface* routerIf = NULL;
    Dict* routerConf = Dict_getDict(&config, String_CONST("router"));
    Dict* iface = Dict_getDict(routerConf, String_CONST("interface"));
    if (String_equals(Dict_getString(iface, String_CONST("type")), String_CONST("TUNInterface"))) {
        String* ifName = Dict_getString(iface, String_CONST("tunDevice"));

        char assignedTunName[TUNConfigurator_IFNAMSIZ];
        void* tunPtr = TUNConfigurator_initTun(((ifName) ? ifName->bytes : NULL),
                                               assignedTunName,
                                               logger,
                                               AbortHandler_INSTANCE);
        struct Jmp jmp;
        Jmp_try(jmp) {
            TUNConfigurator_setIpAddress(
                assignedTunName, myAddr.ip6.bytes, 8, logger, &jmp.handler);
        } Jmp_catch {
            Log_warn(logger, "Unable to configure ip address [%s]", jmp.message);
        }

        struct TUNInterface* tun = TUNInterface_new(tunPtr, eventBase, allocator);
        routerIf = &tun->iface;

    }
Exemplo n.º 15
0

    // --------------------- Configuration ------------------------- //
    struct sockaddr_storage* adminAddr;
    int adminAddrLen;
    String* adminPassword;
    Admin_getConnectInfo(&adminAddr, &adminAddrLen, &adminPassword, admin);
    Configurator_config(&config,
                        adminAddr,
                        adminAddrLen,
                        adminPassword,
                        eventBase,
                        logger,
                        allocator);

    uint8_t address[53];
    Base32_encode(address, 53, myAddr.key, 32);
    Log_info(logger, "Your address is: %s.k\n", address);
    uint8_t myIp[40];
    Address_printIp(myIp, &myAddr);
    Log_info(logger, "Your IPv6 address is: %s\n", myIp);

    // Security.
    security(Dict_getList(&config, String_CONST("security")), logger, AbortHandler_INSTANCE);

    event_base_loop(eventBase, 0);
abort();
    // Never reached.
    return 0;
}
Exemplo n.º 16
0
static void routerConfig(Dict* routerConf, struct Allocator* tempAlloc, struct Context* ctx)
{
    tunInterface(Dict_getDict(routerConf, String_CONST("interface")), tempAlloc, ctx);
    ipTunnel(Dict_getDict(routerConf, String_CONST("ipTunnel")), tempAlloc, ctx);
    supernodes(Dict_getList(routerConf, String_CONST("supernodes")), tempAlloc, ctx);
}
Exemplo n.º 17
0
static void udpInterface(Dict* config, struct Context* ctx)
{
    List* ifaces = Dict_getList(config, String_CONST("UDPInterface"));
    if (!ifaces) {
        ifaces = List_new(ctx->alloc);
        List_addDict(ifaces, Dict_getDict(config, String_CONST("UDPInterface")), ctx->alloc);
    }

    uint32_t count = List_size(ifaces);
    for (uint32_t i = 0; i < count; i++) {
        Dict *udp = List_getDict(ifaces, i);
        if (!udp) {
            continue;
        }
        // Setup the interface.
        String* bindStr = Dict_getString(udp, String_CONST("bind"));
        Dict* d = Dict_new(ctx->alloc);
        if (bindStr) {
            Dict_putString(d, String_CONST("bindAddress"), bindStr, ctx->alloc);
        }
        Dict* resp = NULL;
        rpcCall0(String_CONST("UDPInterface_new"), d, ctx, ctx->alloc, &resp, true);
        int ifNum = *(Dict_getInt(resp, String_CONST("interfaceNumber")));

        // Make the connections.
        Dict* connectTo = Dict_getDict(udp, String_CONST("connectTo"));
        if (connectTo) {
            struct Dict_Entry* entry = *connectTo;
            struct Allocator* perCallAlloc = Allocator_child(ctx->alloc);
            while (entry != NULL) {
                String* key = (String*) entry->key;
                if (entry->val->type != Object_DICT) {
                    Log_critical(ctx->logger, "interfaces.UDPInterface.connectTo: entry [%s] "
                                 "is not a dictionary type.", key->bytes);
                    exit(-1);
                }
                Dict* value = entry->val->as.dictionary;
                Log_keys(ctx->logger, "Attempting to connect to node [%s].", key->bytes);
                key = String_clone(key, perCallAlloc);
                char* lastColon = CString_strrchr(key->bytes, ':');

                if (!Sockaddr_parse(key->bytes, NULL)) {
                    // it's a sockaddr, fall through
                } else if (lastColon) {
                    // try it as a hostname.
                    Log_critical(ctx->logger, "Couldn't add connection [%s], "
                                 "hostnames aren't supported.", key->bytes);
                    exit(-1);
                }
                Dict_putInt(value, String_CONST("interfaceNumber"), ifNum, perCallAlloc);
                Dict_putString(value, String_CONST("address"), key, perCallAlloc);
                rpcCall(String_CONST("UDPInterface_beginConnection"), value, ctx, perCallAlloc);

                // Make a IPTunnel exception for this node
                Dict* aed = Dict_new(perCallAlloc);
                *lastColon = '\0';
                Dict_putString(aed, String_CONST("route"), String_new(key->bytes, perCallAlloc),
                               perCallAlloc);
                *lastColon = ':';
                rpcCall(String_CONST("RouteGen_addException"), aed, ctx, perCallAlloc);

                entry = entry->next;
            }
            Allocator_free(perCallAlloc);
        }
    }
}
Exemplo n.º 18
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
    Crypto_init();
    assert(argc > 0);

    if (argc == 1) { // no arguments
        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
        }
    }
    if (argc == 2) { // one argument
        if (strcmp(argv[1], "--help") == 0) {
            return usage(argv[0]);
        } else if (strcmp(argv[1], "--genconf") == 0) {
            return genconf();
        } else if (strcmp(argv[1], "--getcmds") == 0) {
            // Performed after reading the configuration
        } else if (strcmp(argv[1], "--pidfile") == 0) {
            // Performed after reading the configuration
        } 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;
        }
    }
    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;
    }

    struct Context context;
    memset(&context, 0, sizeof(struct Context));
    context.base = event_base_new();

    // Allow it to allocate 4MB
    context.allocator = MallocAllocator_new(1<<22);
    struct Reader* reader = FileReader_new(stdin, context.allocator);
    Dict config;
    if (JsonBencSerializer_get()->parseDictionary(reader, context.allocator, &config)) {
        fprintf(stderr, "Failed to parse configuration.\n");
        return -1;
    }

    if (argc == 2 && strcmp(argv[1], "--getcmds") == 0) {
        return getcmds(&config);
    }
    if (argc == 2 && strcmp(argv[1], "--pidfile") == 0) {
        pidfile(&config);
        return 0;
    }

    char* user = setUser(Dict_getList(&config, BSTR("security")));

    // Admin
    Dict* adminConf = Dict_getDict(&config, BSTR("admin"));
    if (adminConf) {
        admin(adminConf, user, &context);
    }

    // Logging
    struct Writer* logwriter = FileWriter_new(stdout, context.allocator);
    struct Log logger = { .writer = logwriter };
    context.logger = &logger;

    struct Address myAddr;
    uint8_t privateKey[32];
    parsePrivateKey(&config, &myAddr, privateKey);

    context.eHandler = AbortHandler_INSTANCE;
    context.switchCore = SwitchCore_new(context.logger, context.allocator);
    context.ca =
        CryptoAuth_new(&config, context.allocator, privateKey, context.base, context.logger);
    context.registry = DHTModules_new(context.allocator);
    ReplyModule_register(context.registry, context.allocator);

    // Router
    Dict* routerConf = Dict_getDict(&config, BSTR("router"));
    registerRouter(routerConf, myAddr.key, &context);

    SerializationModule_register(context.registry, context.allocator);

    // Authed passwords.
    List* authedPasswords = Dict_getList(&config, BSTR("authorizedPasswords"));
    if (authedPasswords) {
        authorizedPasswords(authedPasswords, &context);
    }

    // Interfaces.
    Dict* interfaces = Dict_getDict(&config, BSTR("interfaces"));
    Dict* udpConf = Dict_getDict(interfaces, BSTR("UDPInterface"));

    if (udpConf) {
        configureUDP(udpConf, &context);
    }

    if (udpConf == NULL) {
        fprintf(stderr, "No interfaces configured to connect to.\n");
        return -1;
    }

    // pid file
    String* pidFile = Dict_getString(&config, BSTR("pidFile"));
    if (pidFile) {
        Log_info1(context.logger, "Writing pid of process to [%s].\n", pidFile->bytes);
        FILE* pf = fopen(pidFile->bytes, "w");
        if (!pf) {
            Log_critical2(context.logger,
                          "Failed to open pid file [%s] for writing, errno=%d\n",
                          pidFile->bytes,
                          errno);
            return -1;
        }
        fprintf(pf, "%d", getpid());
        fclose(pf);
    }

    Ducttape_register(&config,
                      privateKey,
                      context.registry,
                      context.routerModule,
                      context.routerIf,
                      context.switchCore,
                      context.base,
                      context.allocator,
                      context.logger);

    uint8_t address[53];
    Base32_encode(address, 53, myAddr.key, 32);
    Log_info1(context.logger, "Your address is: %s.k\n", address);
    uint8_t myIp[40];
    Address_printIp(myIp, &myAddr);
    Log_info1(context.logger, "Your IPv6 address is: %s\n", myIp);

    // Security.
    security(Dict_getList(&config, BSTR("security")), context.logger, context.eHandler);

    event_base_loop(context.base, 0);

    // Never reached.
    return 0;
}
Exemplo n.º 19
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

    if (argc < 2) {
        // Fall through.
    } else if (!CString_strcmp("angel", argv[1])) {
        return AngelInit_main(argc, argv);
    } else if (!CString_strcmp("core", argv[1])) {
        return Core_main(argc, argv);
    }

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

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

    if (argc == 2) {
        // one argument
        if ((CString_strcmp(argv[1], "--help") == 0) || (CString_strcmp(argv[1], "-h") == 0)) {
            return usage(allocator, argv[0]);
        } else if (CString_strcmp(argv[1], "--genconf") == 0) {
            return genconf(rand);
        } else if (CString_strcmp(argv[1], "--pidfile") == 0) {
            // deprecated
            fprintf(stderr, "'--pidfile' option is deprecated.\n");
            return 0;
        } else if (CString_strcmp(argv[1], "--reconf") == 0) {
            // Performed after reading the configuration
        } else if (CString_strcmp(argv[1], "--bench") == 0) {
            return benchmark();
        } else if ((CString_strcmp(argv[1], "--version") == 0)
            || (CString_strcmp(argv[1], "-v") == 0))
        {
            printf("Cjdns protocol version: %d\n", Version_CURRENT_PROTOCOL);
            return 0;
        } else if (CString_strcmp(argv[1], "--cleanconf") == 0) {
            // Performed after reading configuration
        } else if (CString_strcmp(argv[1], "--nobg") == 0) {
            // Performed while reading configuration
        } 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 [%s]\n", argv[0], argv[1]);
        fprintf(stderr, "Try `%s --help' for more information.\n", argv[0]);
        // because of '--pidfile $filename'?
        if (CString_strcmp(argv[1], "--pidfile") == 0)
        {
            fprintf(stderr, "\n'--pidfile' option is deprecated.\n");
        }
        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(allocator, 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;
    }

    if (argc == 2 && CString_strcmp(argv[1], "--cleanconf") == 0) {
        struct Writer* stdoutWriter = FileWriter_new(stdout, allocator);
        JsonBencSerializer_get()->serializeDictionary(stdoutWriter, &config);
        printf("\n");
        return 0;
    }

    int forceNoBackground = 0;
    if (argc == 2 && CString_strcmp(argv[1], "--nobg") == 0) {
        forceNoBackground = 1;
    }

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

    // --------------------- 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 = CString_strlen(adminPass->bytes);
    }
    if (!adminBind) {
        Except_throw(eh, "You must specify admin.bind in the cjdroute.conf file.");
    }

    // --------------------- Welcome to cjdns ---------------------- //
    char* archInfo = ArchInfo_describe(ArchInfo_detect(), allocator);
    char* sysInfo = SysInfo_describe(SysInfo_detect(), allocator);
    Log_info(logger, "Cjdns %s %s", archInfo, sysInfo);

    // --------------------- Check for running instance  --------------------- //

    Log_info(logger, "Checking for running instance...");
    checkRunningInstance(allocator, eventBase, adminBind, adminPass, logger, eh);

    // --------------------- Setup Pipes to Angel --------------------- //
    char angelPipeName[64] = "client-angel-";
    Random_base32(rand, (uint8_t*)angelPipeName+13, 31);
    Assert_ifParanoid(EventBase_eventCount(eventBase) == 0);
    struct Pipe* angelPipe = Pipe_named(angelPipeName, eventBase, eh, allocator);
    Assert_ifParanoid(EventBase_eventCount(eventBase) == 2);
    angelPipe->logger = logger;

    char* args[] = { "angel", angelPipeName, NULL };

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

    char* corePath = Process_getPath(allocator);

    if (!corePath) {
        Except_throw(eh, "Can't find a usable cjdns core executable, "
                         "make sure it is in the same directory as cjdroute");
    }

    if (!privateKey) {
        Except_throw(eh, "Need to specify privateKey.");
    }
    Log_info(logger, "Forking angel to background.");
    Process_spawn(corePath, args, eventBase, allocator);

    // --------------------- Get user for angel to setuid() ---------------------- //
    String* securityUser = NULL;
    List* securityConf = Dict_getList(&config, String_CONST("security"));
    for (int i = 0; securityConf && 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"), String_new(corePath, allocator), 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);
    }
    Dict* logging = Dict_getDict(&config, String_CONST("logging"));
    if (logging) {
        Dict_putDict(preConf, String_CONST("logging"), logging, allocator);
    }

    struct Message* toAngelMsg = Message_new(0, 1024, allocator);
    BencMessageWriter_write(preConf, toAngelMsg, eh);
    Interface_sendMessage(&angelPipe->iface, toAngelMsg);

    Log_debug(logger, "Sent [%d] bytes to angel process", toAngelMsg->length);

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

    struct Message* fromAngelMsg =
        InterfaceWaiter_waitForData(&angelPipe->iface, eventBase, allocator, eh);
    Dict* responseFromAngel = BencMessageReader_read(fromAngelMsg, allocator, eh);

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

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

    // sanity check, Pipe_named() creates 2 events, see above.
    Assert_ifParanoid(EventBase_eventCount(eventBase) == 2);

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

    // --------------------- noBackground ------------------------ //

    int64_t* noBackground = Dict_getInt(&config, String_CONST("noBackground"));
    if (forceNoBackground || (noBackground && *noBackground)) {
        EventBase_beginLoop(eventBase);
    }

    //Allocator_free(allocator);
    return 0;
}
Exemplo n.º 20
0
static void runTest0(char** prefixes,
                     char** exceptions4,
                     char** exceptions6,
                     char** expectedOut4,
                     char** expectedOut6,
                     struct Allocator* alloc,
                     struct Log* log)
{
    struct RouteGen* rg = RouteGen_new(alloc, log);
    for (int i = 0; prefixes[i]; i++) {
        RouteGen_addPrefix(rg, mkSockaddr(prefixes[i], alloc));
    }
    for (int i = 0; exceptions4 && exceptions4[i]; i++) {
        RouteGen_addException(rg, mkSockaddr(exceptions4[i], alloc));
    }
    for (int i = 0; exceptions6 && exceptions6[i]; i++) {
        RouteGen_addException(rg, mkSockaddr(exceptions6[i], alloc));
    }
    Dict* routes = RouteGen_getGeneratedRoutes(rg, alloc);
    List* routes4 = Dict_getList(routes, String_CONST("ipv4"));
    List* routes6 = Dict_getList(routes, String_CONST("ipv6"));
    if (expectedOut4) {
        for (int i = 0; expectedOut4[i]; i++) {
            Log_debug(log, "%s\n", expectedOut4[i]);
        }
        for (int i = 0; i < List_size(routes4); i++) {
            Log_debug(log, "%s\n", List_getString(routes4, i)->bytes);
        }

        Assert_true(!expectedOut4[List_size(routes4)]);
        for (int i = 0; i < List_size(routes4); i++) {
            String* str = List_getString(routes4, i);
            Assert_true(str);
            Assert_true(expectedOut4[i]);
            if (CString_strncmp(expectedOut4[i], str->bytes, str->len)) {
                Log_error(log, "Fail\nexpected: %s\nGot:      %s\n", expectedOut4[i], str->bytes);
                Assert_failure("fail");
            }
        }
    } else {
        Assert_true(!List_size(routes4));
    }
    if (expectedOut6) {
        for (int i = 0; expectedOut6[i]; i++) {
            Log_debug(log, "%s\n", expectedOut6[i]);
        }
        for (int i = 0; i < List_size(routes6); i++) {
            Log_debug(log, "%s\n", List_getString(routes6, i)->bytes);
        }

        Assert_true(!expectedOut6[List_size(routes6)]);
        for (int i = 0; i < List_size(routes6); i++) {
            String* str = List_getString(routes6, i);
            Assert_true(str);
            Assert_true(expectedOut6[i]);
            if (CString_strncmp(expectedOut6[i], str->bytes, str->len)) {
                Log_error(log, "Fail\nexpected: %s\nGot:      %s\n", expectedOut6[i], str->bytes);
                Assert_failure("fail");
            }
        }
    } else {
        Assert_true(!List_size(routes6));
    }
}
Exemplo n.º 21
0
static void ethInterface(Dict* config, struct Context* ctx)
{
    List* ifaces = Dict_getList(config, String_CONST("ETHInterface"));
    if (!ifaces) {
        ifaces = List_addDict(ifaces,
                              Dict_getDict(config, String_CONST("ETHInterface")), ctx->alloc);
    }

    uint32_t count = List_size(ifaces);
    for (uint32_t i = 0; i < count; i++) {
        Dict *eth = List_getDict(ifaces, i);
        if (!eth) {
            continue;
        }
        // Setup the interface.
        String* deviceStr = Dict_getString(eth, String_CONST("bind"));
        Log_info(ctx->logger, "Setting up ETHInterface [%d].", i);
        Dict* d = Dict_new(ctx->alloc);
        if (deviceStr) {
            Log_info(ctx->logger, "Binding to device [%s].", deviceStr->bytes);
            Dict_putString(d, String_CONST("bindDevice"), deviceStr, ctx->alloc);
        }
        if (rpcCall0(String_CONST("ETHInterface_new"), d, ctx, ctx->alloc, false)) {
            Log_warn(ctx->logger, "Failed to create ETHInterface.");
            continue;
        }

        // Make the connections.
        Dict* connectTo = Dict_getDict(eth, String_CONST("connectTo"));
        if (connectTo) {
            Log_info(ctx->logger, "ETHInterface should connect to a specific node.");
            struct Dict_Entry* entry = *connectTo;
            while (entry != NULL) {
                String* key = (String*) entry->key;
                if (entry->val->type != Object_DICT) {
                    Log_critical(ctx->logger, "interfaces.ETHInterface.connectTo: entry [%s] "
                                               "is not a dictionary type.", key->bytes);
                    exit(-1);
                }
                Dict* value = entry->val->as.dictionary;

                Log_keys(ctx->logger, "Attempting to connect to node [%s].", key->bytes);

                struct Allocator* perCallAlloc = Allocator_child(ctx->alloc);
                // Turn the dict from the config into our RPC args dict by filling in all
                // the arguments,
                Dict_putString(value, String_CONST("macAddress"), key, perCallAlloc);
                Dict_putInt(value, String_CONST("interfaceNumber"), i, perCallAlloc);
                rpcCall(String_CONST("ETHInterface_beginConnection"), value, ctx, perCallAlloc);
                Allocator_free(perCallAlloc);

                entry = entry->next;
            }
        }

        int64_t* beaconP = Dict_getInt(eth, String_CONST("beacon"));
        if (beaconP) {
            int64_t beacon = *beaconP;
            if (beacon > 3 || beacon < 0) {
                Log_error(ctx->logger, "interfaces.ETHInterface.beacon may only be 0, 1,or 2");
            } else {
                // We can cast beacon to an int here because we know it's small enough
                Log_info(ctx->logger, "Setting beacon mode on ETHInterface to [%d].", (int) beacon);
                Dict d = Dict_CONST(String_CONST("interfaceNumber"), Int_OBJ(i),
                         Dict_CONST(String_CONST("state"), Int_OBJ(beacon), NULL));
                rpcCall(String_CONST("ETHInterface_beacon"), &d, ctx, ctx->alloc);
            }
        }
    }
}