#include #include #include #include #include #include // for multithreaded version (multiplatorm) #include // Linux needs this for SIGINT #include #ifdef _WIN32 #define uint UINT #endif #if(__FreeBSD__) || (__OpenBSD__) || (__NetBSD__) #include #endif // CHECK: is multiprocess still a thing? #ifndef TESTNET #define TESTNET 0 #endif struct llarp_main *ctx = 0; bool done = false; void handle_signal(int sig) { printf("got SIGINT\n"); done = true; // if using router, signal it if(ctx) llarp_main_signal(ctx, sig); } struct dns_relay_config { std::string upstream_host; uint16_t upstream_port; void dns_iter_config(const char *section, const char *key, const char *val) { if(!strcmp(section, "dns")) { if(!strcmp(key, "upstream-server")) { upstream_host = strdup(val); llarp::LogDebug("Config file setting dns server to ", upstream_host); } if(!strcmp(key, "upstream-port")) { upstream_port = atoi(val); llarp::LogDebug("Config file setting dns server port to ", upstream_port); } } } }; int main(int argc, char *argv[]) { int code = 1; char cwd[1024]; char *ptr = getcwd(cwd, sizeof(cwd)); llarp::LogInfo("Starting up server at ", ptr); const char *conffname = handleBaseCmdLineArgs(argc, argv); dns_relay_config dnsr_config; dnsr_config.upstream_host = "8.8.8.8"; dnsr_config.upstream_port = 53; llarp::Config config_reader; if(config_reader.load(conffname)) { llarp::LogError("failed to load config file ", conffname); return 0; } using namespace std::placeholders; config_reader.visit( std::bind(&dns_relay_config::dns_iter_config, &dnsr_config, _1, _2, _3)); llarp::LogInfo("config [", conffname, "] loaded"); const uint16_t server_port = 53; dns_iptracker_init(); // llarp::SetLogLevel(llarp::eLogDebug); bool enableDLL = false; bool useLlarp = true; if(enableDLL) { // libev version w/router context ctx = llarp_main_init(conffname, !TESTNET); if(!ctx) { llarp::LogError("Cant set up context"); return 0; } llarp_main_setup(ctx); signal(SIGINT, handle_signal); // we can't programmatic force a client // but we'll need to be one... /* struct dnsd_context dnsd; llarp::Addr dnsd_sockaddr(127, 0, 0, 1, 53); llarp::Addr dnsc_sockaddr(dnsr_config.upstream_host, dnsr_config.upstream_port); // server_port, (const char *)dnsr_config.upstream_host.c_str(), // dnsr_config.upstream_port if(!llarp_main_init_dnsd(ctx, &dnsd, dnsd_sockaddr, dnsc_sockaddr)) { llarp::LogError("Couldnt init dns daemon"); } // Configure intercept dnsd.intercept = &llarp_dotlokilookup_handler; dotLokiLookup dll; */ // should be a function... // dll.tunEndpoint = main_router_getFirstTunEndpoint(ctx); // dll.ip_tracker = &g_dns_iptracker; /* llarp_main_init_dotLokiLookup(ctx, &dll); dnsd.user = &dll; // check tun set up llarp_tun_io *tun = main_router_getRange(ctx); llarp::LogDebug("TunNetmask: ", tun->netmask); llarp::LogDebug("TunIfAddr: ", tun->ifaddr); // configure dns_ip_tracker to use this // well our routes table should already be set up // mark our TunIfAddr as used if(tun) { dll.user = tun; struct sockaddr_in addr; addr.sin_addr.s_addr = inet_addr(tun->ifaddr); addr.sin_family = AF_INET; llarp::Addr tunIp(addr); llarp::LogDebug("llarp::TunIfAddr: ", tunIp); dns_iptracker_setup_dotLokiLookup(&dll, tunIp); dns_iptracker_setup(tunIp); } else { llarp::LogWarn("No tun interface, can't look up .loki"); } */ // run system and wait llarp_main_run(ctx); llarp_main_free(ctx); } else if(useLlarp) { // libev version llarp_ev_loop *netloop = nullptr; llarp_threadpool *worker = nullptr; llarp::Logic *logic = nullptr; llarp_ev_loop_alloc(&netloop); // set up netio worker worker = llarp_init_same_process_threadpool(); logic = new llarp::Logic(worker); // set up logic worker // configure main netloop struct dnsd_context dnsd; llarp::Addr dnsd_sockaddr(127, 0, 0, 1, 53); llarp::Addr dnsc_sockaddr(dnsr_config.upstream_host, dnsr_config.upstream_port); llarp::LogInfo("dnsd_sockaddr init: ", dnsd_sockaddr); llarp::LogInfo("dnsc_sockaddr init: ", dnsc_sockaddr); if(!llarp_dnsd_init(&dnsd, logic, netloop, dnsd_sockaddr, dnsc_sockaddr)) { // llarp::LogError("failed to initialize dns subsystem"); llarp::LogError("Couldnt init dns daemon"); return 0; } // Configure intercept dnsd.intercept = &llarp_dotlokilookup_handler; llarp::LogInfo("singlethread start"); llarp_ev_loop_run_single_process(netloop, worker, logic); llarp::LogInfo("singlethread end"); llarp_ev_loop_free(&netloop); } else { // need this for timer stuff llarp_threadpool *worker = llarp_init_same_process_threadpool(); llarp::Logic *logic = new llarp::Logic(worker); // configure main netloop struct dnsd_context dnsd; llarp::Addr dnsd_sockaddr(127, 0, 0, 1, 53); llarp::Addr dnsc_sockaddr(dnsr_config.upstream_host, dnsr_config.upstream_port); if(!llarp_dnsd_init(&dnsd, logic, nullptr, dnsd_sockaddr, dnsc_sockaddr)) { // llarp::LogError("failed to initialize dns subsystem"); llarp::LogError("Couldnt init dns daemon"); return 0; } // Configure intercept dnsd.intercept = &llarp_dotlokilookup_handler; struct sockaddr_in m_address; int m_sockfd; #ifndef _WIN32 m_sockfd = socket(AF_INET, SOCK_DGRAM, 0); #else m_sockfd = WSASocket(AF_INET, SOCK_DGRAM, 0, nullptr, 0, WSA_FLAG_OVERLAPPED); #endif m_address.sin_family = AF_INET; m_address.sin_addr.s_addr = INADDR_ANY; m_address.sin_port = htons(server_port); int rbind = bind(m_sockfd, (struct sockaddr *)&m_address, sizeof(struct sockaddr_in)); if(rbind != 0) { llarp::LogError("Could not bind: ", strerror(errno)); return 0; } const size_t BUFFER_SIZE = 1024; char buffer[BUFFER_SIZE]; // 1024 is buffer size struct sockaddr_in clientAddress; socklen_t addrLen = sizeof(struct sockaddr_in); struct timeval tv; tv.tv_sec = 0; tv.tv_usec = 100 * 1000; // 1 sec #ifndef _WIN32 if(setsockopt(m_sockfd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0) #else if(setsockopt(m_sockfd, SOL_SOCKET, SO_RCVTIMEO, (const char *)&tv, sizeof(tv)) < 0) #endif { perror("Error"); } signal(SIGINT, handle_signal); while(!done) { // sigint quits after next packet int nbytes = recvfrom(m_sockfd, buffer, BUFFER_SIZE, 0, (struct sockaddr *)&clientAddress, &addrLen); if(nbytes == -1) continue; llarp::LogInfo("Received Bytes ", nbytes); llarp_buffer_t lbuffer; lbuffer.base = (byte_t *)buffer; lbuffer.cur = lbuffer.base; lbuffer.sz = nbytes; dns_msg_header hdr; if(!decode_hdr(&lbuffer, &hdr)) { llarp::LogError("failed to decode dns header"); continue; } // if we sent this out, then there's an id struct dns_tracker *tracker = (struct dns_tracker *)dnsd.client.tracker; struct dnsc_answer_request *request = tracker->client_request[hdr.id].get(); if(request) { request->packet.header = hdr; generic_handle_dnsc_recvfrom(tracker->client_request[hdr.id].get(), lbuffer, &hdr); } else { llarp::LogWarn("Ignoring multiple responses on ID #", hdr.id); } // raw_handle_recvfrom(&m_sockfd, (const struct sockaddr *)&clientAddress, // buffer, nbytes); } } return code; }