Commit f22f5226 authored by Marek Vavrusa's avatar Marek Vavrusa Committed by Ondřej Surý

daemon: ported DNS/TLS preparation code to 1.1

parent 316f24fb
......@@ -150,6 +150,8 @@ static int net_list_add(const char *key, void *val, void *ext)
lua_setfield(L, -2, "udp");
lua_pushboolean(L, ep->flags & NET_TCP);
lua_setfield(L, -2, "tcp");
lua_pushboolean(L, ep->flags & NET_TLS);
lua_setfield(L, -2, "tls");
}
lua_setfield(L, -2, key);
return kr_ok();
......@@ -165,7 +167,7 @@ static int net_list(lua_State *L)
}
/** Listen on interface address list. */
static int net_listen_iface(lua_State *L, int port)
static int net_listen_iface(lua_State *L, int port, int flags)
{
/* Expand 'addr' key if exists */
lua_getfield(L, 1, "addr");
......@@ -180,7 +182,7 @@ static int net_listen_iface(lua_State *L, int port)
for (size_t i = 0; i < count; ++i) {
lua_rawgeti(L, -1, i + 1);
int ret = network_listen(&engine->net, lua_tostring(L, -1),
port, NET_TCP|NET_UDP);
port, flags);
if (ret != 0) {
kr_log_info("[system] bind to '%s#%d' %s\n", lua_tostring(L, -1), port, kr_strerror(ret));
}
......@@ -191,6 +193,17 @@ static int net_listen_iface(lua_State *L, int port)
return 1;
}
static bool table_get_flag(lua_State *L, int index, const char *key, bool def)
{
bool result = def;
lua_getfield(L, index, key);
if (lua_isboolean(L, -1)) {
result = lua_toboolean(L, -1);
}
lua_pop(L, 1);
return result;
}
/** Listen on endpoint. */
static int net_listen(lua_State *L)
{
......@@ -200,18 +213,23 @@ static int net_listen(lua_State *L)
if (n > 1 && lua_isnumber(L, 2)) {
port = lua_tointeger(L, 2);
}
bool tls = (port == KR_DNS_TLS_PORT);
if (n > 2 && lua_istable(L, 3)) {
tls = table_get_flag(L, 3, "tls", tls);
}
/* Process interface or (address, port) pair. */
/* Process interface or (address, port, flags) triple. */
int flags = tls ? (NET_TCP|NET_TLS) : (NET_TCP|NET_UDP);
if (lua_istable(L, 1)) {
return net_listen_iface(L, port);
return net_listen_iface(L, port, flags);
} else if (n < 1 || !lua_isstring(L, 1)) {
format_error(L, "expected 'listen(string addr, number port = 53)'");
format_error(L, "expected 'listen(string addr, number port = 53[, bool tls = false])'");
lua_error(L);
}
/* Open resolution context cache */
struct engine *engine = engine_luaget(L);
int ret = network_listen(&engine->net, lua_tostring(L, 1), port, NET_TCP|NET_UDP);
int ret = network_listen(&engine->net, lua_tostring(L, 1), port, flags);
if (ret != 0) {
format_error(L, kr_strerror(ret));
lua_error(L);
......
......@@ -224,7 +224,7 @@ static void tcp_recv(uv_stream_t *handle, ssize_t nread, const uv_buf_t *buf)
mp_flush(worker->pkt_pool.ctx);
}
static void tcp_accept(uv_stream_t *master, int status)
static void _tcp_accept(uv_stream_t *master, int status, bool tls)
{
if (status != 0) {
return;
......@@ -244,6 +244,7 @@ static void tcp_accept(uv_stream_t *master, int status)
* It will re-check every half of a request time limit if the connection
* is idle and should be terminated, this is an educated guess. */
struct session *session = client->data;
session->has_tls = tls;
uv_timer_t *timer = &session->timeout;
uv_timer_init(master->loop, timer);
timer->data = client;
......@@ -251,6 +252,16 @@ static void tcp_accept(uv_stream_t *master, int status)
io_start_read((uv_handle_t *)client);
}
static void tcp_accept(uv_stream_t *master, int status)
{
_tcp_accept(master, status, false);
}
static void tls_accept(uv_stream_t *master, int status)
{
_tcp_accept(master, status, true);
}
static int set_tcp_option(uv_handle_t *handle, int option, int val)
{
uv_os_fd_t fd = 0;
......@@ -307,6 +318,11 @@ int tcp_bind(uv_tcp_t *handle, struct sockaddr *addr)
return _tcp_bind(handle, addr, tcp_accept);
}
int tcp_bind_tls(uv_tcp_t *handle, struct sockaddr *addr)
{
return _tcp_bind(handle, addr, tls_accept);
}
int tcp_bindfd(uv_tcp_t *handle, int fd)
{
if (!handle) {
......
......@@ -28,6 +28,7 @@ struct qr_task;
struct session {
bool outgoing;
bool throttled;
bool has_tls;
uv_timer_t timeout;
struct qr_task *buffering;
array_t(struct qr_task *) tasks;
......@@ -39,6 +40,7 @@ struct session *session_new(void);
int udp_bind(uv_udp_t *handle, struct sockaddr *addr);
int udp_bindfd(uv_udp_t *handle, int fd);
int tcp_bind(uv_tcp_t *handle, struct sockaddr *addr);
int tcp_bind_tls(uv_tcp_t *handle, struct sockaddr *addr);
int tcp_bindfd(uv_tcp_t *handle, int fd);
void io_create(uv_loop_t *loop, uv_handle_t *handle, int type);
......
......@@ -276,6 +276,7 @@ static void help(int argc, char *argv[])
printf("Usage: %s [parameters] [rundir]\n", argv[0]);
printf("\nParameters:\n"
" -a, --addr=[addr] Server address (default: localhost#53).\n"
" -t, --addr=[addr] Server address for TLS (default: off).\n"
" -S, --fd=[fd] Listen on given fd (handed out by supervisor).\n"
" -c, --config=[path] Config file path (relative to [rundir]) (default: config).\n"
" -k, --keyfile=[path] File containing trust anchors (DS or DNSKEY).\n"
......@@ -382,7 +383,9 @@ int main(int argc, char **argv)
{
int forks = 1;
array_t(char*) addr_set;
array_t(char*) tls_set;
array_init(addr_set);
array_init(tls_set);
array_t(int) fd_set;
array_init(fd_set);
char *keyfile = NULL;
......@@ -394,6 +397,7 @@ int main(int argc, char **argv)
int c = 0, li = 0, ret = 0;
struct option opts[] = {
{"addr", required_argument, 0, 'a'},
{"tls", required_argument, 0, 't'},
{"fd", required_argument, 0, 'S'},
{"config", required_argument, 0, 'c'},
{"keyfile",required_argument, 0, 'k'},
......@@ -404,12 +408,15 @@ int main(int argc, char **argv)
{"help", no_argument, 0, 'h'},
{0, 0, 0, 0}
};
while ((c = getopt_long(argc, argv, "a:S:c:f:k:vqVh", opts, &li)) != -1) {
while ((c = getopt_long(argc, argv, "a:t:S:c:f:k:vqVh", opts, &li)) != -1) {
switch (c)
{
case 'a':
array_push(addr_set, optarg);
break;
case 't':
array_push(tls_set, optarg);
break;
case 'S':
array_push(fd_set, atoi(optarg));
break;
......@@ -556,16 +563,33 @@ int main(int argc, char **argv)
if (ret != 0) {
kr_log_error("[system] listen on fd=%d %s\n", fd_set.at[i], kr_strerror(ret));
ret = EXIT_FAILURE;
break;
}
}
/* Bind to sockets and run */
for (size_t i = 0; i < addr_set.len; ++i) {
int port = 53;
const char *addr = set_addr(addr_set.at[i], &port);
ret = network_listen(&engine.net, addr, (uint16_t)port, NET_UDP|NET_TCP);
if (ret != 0) {
kr_log_error("[system] bind to '%s#%d' %s\n", addr, port, kr_strerror(ret));
ret = EXIT_FAILURE;
if (ret == 0) {
for (size_t i = 0; i < addr_set.len; ++i) {
int port = 53;
const char *addr = set_addr(addr_set.at[i], &port);
ret = network_listen(&engine.net, addr, (uint16_t)port, NET_UDP|NET_TCP);
if (ret != 0) {
kr_log_error("[system] bind to '%s#%d' %s\n", addr, port, kr_strerror(ret));
ret = EXIT_FAILURE;
break;
}
}
}
/* Bind to TLS sockets */
if (ret == 0) {
for (size_t i = 0; i < tls_set.len; ++i) {
int port = 853;
const char *addr = set_addr(tls_set.at[i], &port);
ret = network_listen(&engine.net, addr, (uint16_t)port, NET_TCP|NET_TLS);
if (ret != 0) {
kr_log_error("[system] bind to '%s#%d' (TLS) %s\n", addr, port, kr_strerror(ret));
ret = EXIT_FAILURE;
break;
}
}
}
......@@ -604,6 +628,7 @@ int main(int argc, char **argv)
worker_reclaim(worker);
mp_delete(pool.ctx);
array_clear(addr_set);
array_clear(tls_set);
kr_crypto_cleanup();
return ret;
}
......@@ -130,6 +130,7 @@ static int insert_endpoint(struct network *net, const char *addr, struct endpoin
/** Open endpoint protocols. */
static int open_endpoint(struct network *net, struct endpoint *ep, struct sockaddr *sa, uint32_t flags)
{
int ret = 0;
if (flags & NET_UDP) {
ep->udp = malloc(sizeof(*ep->udp));
if (!ep->udp) {
......@@ -137,7 +138,7 @@ static int open_endpoint(struct network *net, struct endpoint *ep, struct sockad
}
memset(ep->udp, 0, sizeof(*ep->udp));
handle_init(udp, net->loop, ep->udp, sa->sa_family);
int ret = udp_bind(ep->udp, sa);
ret = udp_bind(ep->udp, sa);
if (ret != 0) {
return ret;
}
......@@ -150,13 +151,18 @@ static int open_endpoint(struct network *net, struct endpoint *ep, struct sockad
}
memset(ep->tcp, 0, sizeof(*ep->tcp));
handle_init(tcp, net->loop, ep->tcp, sa->sa_family);
int ret = tcp_bind(ep->tcp, sa);
if (flags & NET_TLS) {
ret = tcp_bind_tls(ep->tcp, sa);
ep->flags |= NET_TLS;
} else {
ret = tcp_bind(ep->tcp, sa);
}
if (ret != 0) {
return ret;
}
ep->flags |= NET_TCP;
}
return kr_ok();
return ret;
}
/** Open fd as endpoint. */
......
......@@ -25,6 +25,7 @@ enum endpoint_flag {
NET_DOWN = 0 << 0,
NET_UDP = 1 << 0,
NET_TCP = 1 << 1,
NET_TLS = 1 << 2,
};
struct endpoint {
......
......@@ -61,6 +61,7 @@ static inline int __attribute__((__cold__)) kr_error(int x) {
* Defines.
*/
#define KR_DNS_PORT 53
#define KR_DNS_TLS_PORT 853
#define KR_EDNS_VERSION 0
#define KR_EDNS_PAYLOAD 4096 /* Default UDP payload (max unfragmented UDP is 1452B) */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment