lokinet/daemon/dns.cpp
despair86 bdc54835c2 initial windows server port. Requires Windows 2000 Server or later.
- updated CMake build script
- builds with Microsoft C++ 19.1x. such builds require Windows 8.1 or later
  unless you have the .NET Server 2003-toolset (v141_xp)
- windows port requires a C++17 compiler since cpp17::filesystem is POSIX-only
- HAVE_CXX17_FILESYSTEM manual toggle in CMake. You must manually specify where
  std::[experimental::]filesystem is defined in LDFLAGS or CMAKE_x_LINKER_FLAGS.
- IPv6 support can be added at any time, and the windows sdk still has that
  inline getaddrinfo(3) if it can't find a suitable IPv6 stack.
- inline code for mingw-w64: there's a few bits and pieces still missing simply because
  mingw-w64 derives its windows sdk from wine and reactos, and then writing all the newer
  stuff into it by hand straight from the MSDN manpages.
- misc. C++11 stuff (nullptr and friends)
- Internal file handling code takes UTF-8 or plain 8-bit text, NTFS is UTF-16, so
  std::filesystem::path::c_str() is wchar_t. That's no good unless you first
  call std::filesystem::path::string().
- implemented getifaddrs(3) and if_nametoindex(3) on top of GetAdapters[Info|Addresses](2).
- updated readme with new info

BONUS: may implement Solaris/illumos IOCP someday...

-despair86
2018-08-01 23:41:02 -05:00

192 lines
4.7 KiB
C++

#include <getopt.h>
#include <signal.h>
#include <stdio.h> /* fprintf, printf */
#ifndef _MSC_VER
#include <unistd.h>
#endif
#include <llarp.h>
#include <llarp/logic.h>
#include "dnsd.hpp"
#include "ev.hpp"
#include "llarp/net.hpp"
#include "logger.hpp"
#include <thread> // for multithreaded version
#include <vector>
// keep this once jeff reenables concurrency
#ifdef _MSC_VER
extern "C" void
SetThreadName(DWORD dwThreadID, LPCSTR szThreadName);
#endif
#ifdef _WIN32
#define uint UINT
#endif
#if(__FreeBSD__) || (__OpenBSD__) || (__NetBSD__)
#include <pthread_np.h>
#endif
struct llarp_main *ctx = 0;
bool done = false;
void
handle_signal(int sig)
{
printf("got SIGINT\n");
done = true;
}
sockaddr *
hookChecker(std::string name, struct dnsd_context *context)
{
llarp::LogInfo("Hooked ", name);
// cast your context->user;
return nullptr;
}
// FIXME: make configurable
#define SERVER "8.8.8.8"
#define PORT 53
struct dns_relay_config
{
std::string upstream_host;
uint16_t upstream_port;
};
void
dns_iter_config(llarp_config_iterator *itr, const char *section,
const char *key, const char *val)
{
dns_relay_config *config = (dns_relay_config *)itr->user;
if(!strcmp(section, "dns"))
{
if(!strcmp(key, "upstream-server"))
{
config->upstream_host = strdup(val);
llarp::LogDebug("Config file setting dns server to ",
config->upstream_host);
}
if(!strcmp(key, "upstream-port"))
{
config->upstream_port = atoi(val);
llarp::LogDebug("Config file setting dns server port to ",
config->upstream_port);
}
}
}
int
main(int argc, char *argv[])
{
int code = 1;
llarp::LogInfo("Starting up server");
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;
llarp_new_config(&config_reader);
// ctx = llarp_main_init(conffname, multiThreaded);
if(llarp_load_config(config_reader, conffname))
{
llarp_free_config(&config_reader);
llarp::LogError("failed to load config file ", conffname);
return false;
}
llarp_config_iterator iter;
iter.user = &dnsr_config;
iter.visit = &dns_iter_config;
llarp_config_iter(config_reader, &iter);
llarp::LogInfo("config [", conffname, "] loaded");
// llarp::SetLogLevel(llarp::eLogDebug);
if(1)
{
// libev version
llarp_ev_loop *netloop = nullptr;
llarp_threadpool *worker = nullptr;
llarp_logic *logic = nullptr;
llarp_ev_loop_alloc(&netloop);
// configure main netloop
struct dnsd_context dnsd;
if(!llarp_dnsd_init(&dnsd, netloop, "*", 1053,
(const char *)dnsr_config.upstream_host.c_str(),
dnsr_config.upstream_port))
{
// llarp::LogError("failed to initialize dns subsystem");
llarp::LogError("Couldnt init dns daemon");
return 0;
}
// Configure intercept
dnsd.intercept = &hookChecker;
llarp::LogInfo("singlethread start");
worker = llarp_init_same_process_threadpool();
logic = llarp_init_single_process_logic(worker);
llarp_ev_loop_run_single_process(netloop, worker, logic);
llarp::LogInfo("singlethread end");
llarp_ev_loop_free(&netloop);
}
else
{
struct sockaddr_in m_address;
int m_sockfd;
m_sockfd = socket(AF_INET, SOCK_DGRAM, 0);
m_address.sin_family = AF_INET;
m_address.sin_addr.s_addr = INADDR_ANY;
m_address.sin_port = htons(1053);
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);
raw_handle_recvfrom(&m_sockfd, (const struct sockaddr *)&clientAddress,
buffer, nbytes);
}
}
return code;
}