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; }
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; }